☰ INDEX
Acute Leukemia, Clinical Features & Classification
Alcoholic Liver Disease
Alports Syndrome
Amyloidosis
Aneurysm
Antigen Presenting Cells & MHC
Apoptosis
Asthma
Atelectasis
Atrophy
Autoimmune Cholangiopathies
Bleeding & Platelet Disorders
Bronchiectasis
CLPN Basics
CNS Tumors
Cellular Ageing
Cellular Events of Inflammation
Chronic Bronchitis
Chronic Inflammation
Chronic Myeloid Leukemia
Chronic Myeloproliferative Neoplasms Introduction
Chronic Pancreatitis
Chronic Pulmonary Disease Classification
Coagulation Pathways & Disorders
Defects of Inflammation
Diabetes Criteria, Classifications & Pathophysiology
Diagnosis of Genetic Disorders
Diseases of Uterus
Emphysema
Esophagus & Stomach
Essential Thromobocythemia
FSGS
Fate of Acute Inflammation
Ferroptosis
Free Radicals
Gall Bladder Stones
Glomerulonephritis Basics
Graft Rejection & GVHD
Hallmarks of Cancer & Cell Cycle
Hemolytic Anemia Classification & Examples
Hepatocellular Tumors & Carcinoma
Hodgkins Lymphoma
Hypersensitivity Pneumonitis
Hypersensitivity Reactions - (Type-1)
Hypersensitivity Reactions - (Type-3 & 4)
Hypertrophic Cardiomyopathy
Hypertrophy & Hyperplasia
Infective Endocarditis
Inflammatory Bowel Diseases
Intracellular Accumulation
Introduction to Cell Injury
Introduction to Immune System Innate & Adaptive Immunity
Ischemic Heart Disease
Leprosy
Lesion of Cervix
Lesions of Breast & Breast CA
Liver Injury
Lung Basics & Congenital Anomalies of Lungs
MCD
MGN
MPGN
Mediators of Inflammation
Mendelian Disorders
Metaplasia
Morphological Types of Acute Inflammation
Morphology of Thrombosis
Muscular Dystrophy & Myopathies
Mutation Types & Pathogenesis
Myasthenia Gravis & Lems
Myelodysplastic syndrome
NAFLD
Necroptosis & Pyroptosis
Necrosis
Neoplasia Basics
Nephrotic Syndrome Basics
Nerve Injury & Demyelinating Neuropathy
Neutrophil Extracellular Traps
Non-Hodgkins Lymphoma
Non-Mendelian Inheritance - (Part -1)
Non-Mendelian Inheritance - (Part-2)
Normal Anatomy & Physiology
Normal Pancreas Histology & Acute Pancreatitis
Normal Vessel, Hypertensive Changes & Sclerosis
O2 Independent Killing
Other Hallmarks of Cancer
Ovarian Tumors
PSGN
Pancreatic Carcinoma
Penis Lesions & Tumors
Plasma Cell Neoplasms
Pneumonia & ARDS
Polycythemia Vera
Primary Meyelofibrosis
Prostate Adenocarcinoma
Pulmonary Edema
RBCs & Anemia Basics
RPGN
Repair & Regeneration
Reversible Injury
Rheumatic Heart Disease
Shock
Small & Large Intestine
Testis Lesions & Tumors
Thrombosis
Thyroiditis & Thyroid Cancers
Tuberculosis
Tumors of Heart
Types of Anemia
Vascular Events of Inflammation
Vascular Tumor
Vasculitis
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "About the given instrument below all of the following statements are true except:", "options": [{"label": "A", "text": "Done for diagnosis of infiltrative and granulomatous diseases", "correct": false}, {"label": "B", "text": "No need for breath-holding during the procedure", "correct": false}, {"label": "C", "text": "Can be done in a prone or lateral position", "correct": false}, {"label": "D", "text": "Platelet count of < 40000/micro L is a contraindication", "correct": true}], "correct_answer": "D. Platelet count of < 40000/micro L is a contraindication", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689150640160-QTDP075001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Platelet count of < 40000/micro L is a contraindication The given image is of Jamshedi’s Bone marrow biopsy needle . Most are 14 to 18 gauge, In most of the situations where bone marrow aspiration is indicated (eg suspected Acute Leukaemia, bone marrow infiltrative disorders), thrombocytopenia is usually present; So, a platelet count of < 40,000/micro L is not a contraindication to bone marrow aspiration .</p>\n<p><strong>Highyeild:</strong></p><p>Indications of Bone marrow biopsy: Dry tap (failure to aspirate marrow): Seen in Aplastic anaemia Myelofibrosis Hairy cell leukaemia Assess bone marrow cellularity: age dependent, normally can be calculated as 100 - age, but should not be below 25%. Assess metastatic involvement of bone marrow. Staging of lymphoma: lymphoma which invades BM directly becomes stage IV. Myeloproliferative neoplasms. Storage disorders like Gaucher's. Contraindications of Bone marrow biopsy: Severe haemophilia. Severe DIC. Severe bleeding disorders. Thrombocytopenia itself is not a contraindication for bone marrow biopsy , but preferably platelet levels should be more than 20,000/ micro L . When there is a contraindication to bone marrow biopsy, aspiration can be performed by a skilled technician. There are no specific contraindications to bone marrow aspiration .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Done for diagnosis of infiltrative and granulomatous diseases. True . Option: B. No need for breath holding during the procedure. True . Option: C. Can be done in a prone or lateral position. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In infants, Bone Marrow biopsy is done from?", "options": [{"label": "A", "text": "Tibia", "correct": true}, {"label": "B", "text": "Sternum", "correct": false}, {"label": "C", "text": "Posterior superior Iliac Spine", "correct": false}, {"label": "D", "text": "Iliac crest", "correct": false}], "correct_answer": "A. Tibia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tibia The iliac crest is the most common site for bone marrow sampling overall in adults , while in children it is the Anterior medial tibial area , below the tibial tuberosity. In infants, marrow can be withdrawn from the medial aspect of the upper end of the tibia just below the level of the tibial tubercle. This site should be used with caution because it is vulnerable to fractures and lacerations of the adjacent major blood vessels. In older children, the tibial cortical bone is usually too dense and the marrow within is normally less active.</p>\n<p><strong>Highyeild:</strong></p><p>Indications of Bone marrow biopsy: Dry tap (failure to aspirate marrow): Seen in Aplastic anaemia Myelofibrosis Hairy cell leukaemia Assess bone marrow cellularity: age dependent, normally can be calculated as 100 - age, but should not be below 25%. Assess metastatic involvement of bone marrow. Staging of lymphoma: lymphoma which invades BM directly becomes stage IV. Myeloproliferative neoplasms. Storage disorders like Gaucher's. Contraindications of Bone marrow biopsy: Severe haemophilia. Severe DIC. Severe bleeding disorders. Thrombocytopenia itself is not a contraindication for bone marrow biopsy , but preferably platelet levels should be more than 20,000/ micro L . When there is a contraindication to bone marrow biopsy, aspiration can be performed by a skilled technician. There are no specific contraindications to bone marrow aspiration .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Sternum. Incorrect . Option: C. Posterior Superior Iliac Spine. Incorrect . Option: D. Iliac crest. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Infectious mononucleosis affects the?", "options": [{"label": "A", "text": "B-cells", "correct": true}, {"label": "B", "text": "T-cells", "correct": false}, {"label": "C", "text": "NK cells", "correct": false}, {"label": "D", "text": "Macrophages", "correct": false}], "correct_answer": "A. B-cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B-cells</p>\n<p><strong>Highyeild:</strong></p><p>Pathogenesis of Infectious Mononucleosis : EBV causes infectious mononucleosis , a benign, self-limited lymphoproliferative disorder , and is associated with the pathogenesis of several human tumours, most commonly certain lymphomas and nasopharyngeal carcinoma . Infectious mononucleosis is characterized by fever, sore throat, generalized lymphadenopathy, splenomegaly, and the appearance in the blood of atypical activated T lymphocytes (mononucleosis cells). Some people develop hepatitis, meningoencephalitis, and pneumonitis. Infectious mononucleosis occurs principally in late adolescents or young adults among upper socioeconomic classes in higher-income nations. In the rest of the world, primary infection with EBV occurs in childhood and is usually asymptomatic. EBV is transmitted by close human contact, frequently through saliva during kissing . It is not known whether the source of the virus is B cells, oropharyngeal epithelial cells, or both . EBV infects B cells and possibly epithelial cells of the oropharynx. It has been hypothesized that EBV initially infects oropharyngeal epithelial cells and then spreads to underlying lymphoid tissue (tonsils and adenoids), where mature B cells are infected. An EBV envelope glycoprotein binds CD21 (CR2) , the receptor for the C3d component of complement , which is present in B cells .' DOWNEY cells are atypical CD8+ T lymphocytes that are characteristic of infectious mononucleosis . DOWNY cells exhibit both suppressor & cytotoxic functions that develop in response to the infected B lymphocytes. Atypical lymphocytes in infectious mononucleosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. T-cells. Incorrect . Option: C. NK cells. Incorrect . Option: D. Macrophages. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Of note, people with X-linked agammaglobulinemia, who lack B cells , do NOT become latently infected with EBV or shed virus , suggesting that B cells are the main reservoir of infection.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In an ablated animal, myeloid series cells are injected. Which of the following is seen after the incubation period -", "options": [{"label": "A", "text": "RBC", "correct": true}, {"label": "B", "text": "Fibroblast", "correct": false}, {"label": "C", "text": "T lymphocytes", "correct": false}, {"label": "D", "text": "Hematopoietic stem cell", "correct": false}], "correct_answer": "A. RBC", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RBC The components of the hematopoietic system have been traditionally divided into the myeloid tissues , which include the bone marrow and the cells derived from it (e.g., red cells, platelets, granulocytes, and monocytes), and the lymphoid tissues , consisting of the thymus, lymph nodes, and spleen. Myeloid cells are WBCs like neutrophils, monocytes, Basophils , RBCs and Platelets . Lymphoid cells include B-Lymphocyte, T-lymphocyte and NK cells. So following the injection of myeloid series cells, RBCs will be released into the peripheral blood.</p>\n<p><strong>Highyeild:</strong></p><p>Blasts or immature cells are large cells with an increase in Nucleus to cytoplasmic ratio (N/C ratio) found in the bone marrow and can be either Myeloblast or Lymohoblast : table,tr,th,td {border:1px solid black;} Myeloblast Lymohoblast ● Moderate cytoplasm. ● Cytoplasmic granules are present. ● Multiple nucleoli present. ● Most characteristic feature: the presence of Auer rods . ● The scant rim of cytoplasm. ● Cytoplasmic granules are absent. ● Nucleoli are absent. Cytochemistry: Myeloperoxidase (MPO) + Sudan Black B + Cytochemistry: Block positivity with Periodic Acid Schiff (PAS) stain . Monoblasts: Non-specific esterase (NSE) + Hairy cell Leukaemia: TRAP + Erythroblasts: Diffuse positivity with PAS T-ALL: TdT +</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Fibroblast. Incorrect . Option: C. T lymphocytes. Incorrect . Option: D. Hematopoietic stem cell. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "AML causing Gum hypertrophy-", "options": [{"label": "A", "text": "M1", "correct": false}, {"label": "B", "text": "M2", "correct": false}, {"label": "C", "text": "M3", "correct": false}, {"label": "D", "text": "M5", "correct": true}], "correct_answer": "D. M5", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>M5 Acute Myeloid Leukaemia.</p>\n<p><strong>Highyeild:</strong></p><p>FAB classification: FAB subtype Name М0 Undifferentiated acute myeloblastic leukemia М1 Acute myeloblastic leukemia with minimal maturation M2 M3 Acute myeloblastic leukemia with maturation M4 Acute promyelocytic leukemia (APL) M4 eos Acute myelomonocytic leukemia M5 Acute myelomonocytic leukemia with eosinophilia M6 Acute monocytic leukemia M7 Acute erythroid leukemia Most common AML: M2 . Least common AML: M7 . MPO negative AML: M0, M6, M7 . Monocytes leukaemias: M4, M5 . AML with Best prognosis: M2 > M3 . AML associated with DIC: M3 . Most common leukaemia in Down’s syndrome: ALL . Most common AML in Down’s syndrome: M7 . AML causing gum hypertrophy: M5 > M4 . AML causing extramedullary blast proliferation (Chloromas): M2, M4, M5 . AML causing blast infiltrations in the skin (leukaemia cutis): M5, M4 . AML causing Bone marrow fibrosis: M7 . AML with NSE positive: M4, M5 & M3 .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A .M1. Incorrect . Option: B. M2. Incorrect . Option: C. M3. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "DIC is common in which AML-", "options": [{"label": "A", "text": "Monocytic (M5)", "correct": false}, {"label": "B", "text": "Promyelocytic (M3)", "correct": true}, {"label": "C", "text": "Erythrocytic (M6)", "correct": false}, {"label": "D", "text": "Megakaryocytic (M7)", "correct": false}], "correct_answer": "B. Promyelocytic (M3)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Promyelocytic (M3) Acute Promyelocytic Leukaemia (APML, M3) cells can induce Disseminated intravascular coagulation (DIC) . AML M3: Acute Promyelocytic Leukaemia Translocation: t(15;17) is seen. Fusion Transcript: PML-RARA Associated with CVS lesions: Non-Bacterial Thrombotic Endocarditis (NBTE) . The most common cause of death: DIC . Cells with multiple Auer rods: Faggot cells . Treatment: All-Trans Retinoic Acid (ATRA) .</p>\n<p><strong>Highyeild:</strong></p><p>Acute Myeloid Leukaemia FAB classification: FAB subtype Name М0 Undifferentiated acute myeloblastic leukemia М1 Acute myeloblastic leukemia with minimal maturation M2 M3 Acute myeloblastic leukemia with maturation M4 Acute promyelocytic leukemia (APL) M4 eos Acute myelomonocytic leukemia M5 Acute myelomonocytic leukemia with eosinophilia M6 Acute monocytic leukemia M7 Acute erythroid leukemia Most common AML: M2 . Least common AML: M7 . MPO negative AML: M0, M6, M7 . Monocytes leukaemias: M4, M5 . AML with Best prognosis: M2 > M3 . AML associated with DIC: M3 . Most common leukaemia in Down’s syndrome: ALL . Most common AML in Down’s syndrome: M7 . AML causing gum hypertrophy: M5 > M4 . AML causing extramedullary blast proliferation (Chloromas): M2, M4, M5 . AML causing blast infiltrations in the skin (leukaemia cutis): M5, M4 . AML causing Bone marrow fibrosis: M7 . AML with NSE positive: M4, M5 & M3 .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Monocytic (M5). Incorrect . Option: C. Erythrocytic (M6). Incorrect . Option: D. Megakaryocytic (M7). Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "40 y/o female presented to AIIMS OPD with the following findings—Hb: 9.8gm%, TLC: 15,700/cumm, Platelet count: 3 lac/cumm. Peripheral smear showed increased neutrophils with 14 % blasts, 15% myelocytes and metamyelocytes with some dysplasia. Cytogenetic study revealed t(8;21). What is your diagnosis?", "options": [{"label": "A", "text": "AML", "correct": true}, {"label": "B", "text": "CML", "correct": false}, {"label": "C", "text": "MDS", "correct": false}, {"label": "D", "text": "ALL", "correct": false}], "correct_answer": "A. AML", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>AML The diagnosis of AML is based on the presence of at least 20% myeloid blasts in the bone marrow . This 40 yr old female is presenting with leukocytosis and increased blast counts in the peripheral smear . The cytogenetic study done here shows t(8;21) . This finding is suggestive of Acute myeloid leukaemia even if there are < 20% blast counts . Some dysplasia can often accompany leukaemias. Some cases of AML have a lower blast per cent than the commonly stated threshold for AML (20%) . These include cytogenetic abnormalities like t(15;17), t(8;21), inv(16) .</p>\n<p><strong>Highyeild:</strong></p><p>Remember: If these genetic abnormalities are encountered in a patient with symptomatic myeloid disleukaemiaL should be diagnosed despite the lower blast per cent.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. For diagnosis of CML, Leukocytosis with the presence of immature myeloid precursors i.e. shift to the left and is associated with basophilia and t (9;22) with fusion transcript BCR-ABL is needed. Option: C. MDS. The periphrastic smear shows Pancytopenia with per cellular bone marrow is seen, it is associated with ineffective hematopoiesis and a high risk of transformation to AML. The most characteristic finding is disordered (dysplastic) differentiation affecting the erythroid, granulocytic, monocytic, and megakaryocytic lineages to varying degrees . Option: D. Acute lymphoblastic leukaemia/lymphomas (ALLs) are neoplasms composed of immature B (pre-B) or T (pre-T) cells, which are referred to as lymphoblasts . The marrow is hypercellular and packed with lymphoblasts , which replace normal marrow elements. T-ALL is TdT + and CD3 + and B-ALL is CD19+, CD10+ and PAX5 + .</p>\n<p><strong>Extraedge:</strong></p><p>Good prognostic markers in AML: All these can be diagnosed even if blasts are less than 20% t(8;21) AMLeto RUNX1/RUNX1T1 M2 t(15;17) PML-RARA M3 inv (16) or t(16;16) CBFB-MYH M4 Poor prognostic markers in AML: t (6;9) t (1;22)</p>\n<p><strong>Table:</strong></p><p>WHO classification of AML: 1. AML with recurrent cytogenetic\naberration 2. AML therapy related 3. AML with Myelodysplasia 4. AML in Down syndrome (Transient\nAML M7) 5. AML NOS (Not otherwise\nspecified)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Good prognostic factors for ALL are all, except:", "options": [{"label": "A", "text": "Hyperdiploidy", "correct": false}, {"label": "B", "text": "Female", "correct": false}, {"label": "C", "text": "T Cell All", "correct": true}, {"label": "D", "text": "t(12;21)", "correct": false}], "correct_answer": "C. T Cell All", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>T Cell All T-cell acute lymphoblastic leukemia (T-Cell ALL) can have a particularly poor prognosis when certain unfavorable factors are present. Worst prognostic factors and characteristics associated with T-Cell ALL include: Philadelphia chromosome,MalePatient, Less than one year and more than 10 years, Mediastinal mass present, Testicular involvement, Hypoploidy and T cell All</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Prognostic Factor Good Prognosis Bad Prognosis Age 2-8 years Less than 1 year,more than 10 years Sex Female Male Genetic Abnormalities Hyperploidy: t (9;12), t (12;21), trisomies 4,10,17 Hypoploidy t (4;11), t (9;22), Bcr-Abl t(8;14), t{1;19) Immunophenotype CD10 + T Cell All Testicular involvement Absent Present Mediastinal mass absent present Richter Transformation No Richter transformation Richter transformation to an aggressive lymphoma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hyperdiploidy. Good prognosis . Option: B. Female. Good prognosis . Option: D. t(12;21). Good prognosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The least likely to be Pre-leukemic condition is:", "options": [{"label": "A", "text": "Paroxysmal nocturnal hemoglobinuria", "correct": false}, {"label": "B", "text": "Paroxysmal cold hemoglobinuria", "correct": true}, {"label": "C", "text": "The diagnostic anemia", "correct": false}, {"label": "D", "text": "Myelodysplastic syndrome", "correct": false}], "correct_answer": "B. Paroxysmal cold hemoglobinuria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Paroxysmal cold hemoglobinuria Preleukemic conditions: Can progress to Leukaemias. Paroxysmal nocturnal hemoglobinuria (PNH) Aplastic anaemia Myelodysplastic syndrome Paroxysmal nocturnal hemoglobinuria (PNH) , Aplastic anaemia & Myelodysplastic syndrome predispose to Leukaemia PNH can progress to aplastic anaemia . All types of Myelodysplastic syndrome (MDS) can progress to AML but there is an increased incidence of therapy-related MDS (t-MDS) . Paroxysmal cold hemoglobinuria is not known to predispose to Leukaemia .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Paroxysmal nocturnal hemoglobinuria. Can progress to Leukaemia . Option: C. Aplastic anaemia. Can progress to Leukaemia . Option: D. Myelodysplastic syndrome. Can progress to Leukaemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "ALL L3 morphology is a malignancy arising from which cell lineage -", "options": [{"label": "A", "text": "Mature B cell", "correct": true}, {"label": "B", "text": "Precursor B cell", "correct": false}, {"label": "C", "text": "Immature T cell", "correct": false}, {"label": "D", "text": "Mixed B cell & T cell", "correct": false}], "correct_answer": "A. Mature B cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mature B cell Uncommon type (1-2%) of ALL cases in children. Both B-cell ALL and Burkitt lymphoma are characterized by FAB L3 morphology . Associated with t(8;14) , and overexpression of the c-myc oncogene . FAB Classification of ALL The FAB Classification relies on morphology, dividing blasts into L1, L2 and L3 by their appearance. These are derived from immunophenotypically distinct mature B cells. FAB Classification of ALL The FAB Classification relies on morphology, dividing blasts into L1, L2 and L3 by their appearance. These are derived from immunophenotypically distinct mature B cells. L1 L2 L3 Small Larger & Small Large Almost no cytoplasm About 20% cytoplasm Basophilic Cytoplasm Cytoplasmic vacuolization Round to cleaved nucleoli Perinuclear chromatin More prominent nucleoli</p>\n<p><strong>Highyeild:</strong></p><p>Good prognostic markers for B-ALL: Age 1-10 yrs Cytogenetics: Hyperdiploidy t (12;21) TEL-AML t (9; 12) Trisomy 4, 7, 10 Poor prognostic markers for B-ALL: Increase in TLC Increase in bast number < 1 year, > 10 years Lymphadenopathy Hepatosplenomegaly Males CNS involvement Testicular involvement Cytogenetics: Hypodiploidy t (9;22) BCR-ABL +, p190 Infantile leukaemia t (variable;11) MLL translocation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Precursor B cell. Incorrect . Option: C. Immature T cell. Incorrect . Option: D. Mixed B cell & T cell. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Non-specific esterase is positive in all the categories of AML except-", "options": [{"label": "A", "text": "M3", "correct": false}, {"label": "B", "text": "M4", "correct": false}, {"label": "C", "text": "M5", "correct": false}, {"label": "D", "text": "M6", "correct": true}], "correct_answer": "D. M6", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>M6 Nonspecific esterase reactivity is found strongly in monocytes & weak positive leukaemia myelocytes, hence showing positive staining in AML-M4, M5 & M3 .</p>\n<p><strong>Highyeild:</strong></p><p>Acute Myeloid Leukaemia FAB classification: FAB subtype Name М0 Undifferentiated acute myeloblastic leukemia М1 Acute myeloblastic leukemia with minimal maturation M2 M3 Acute myeloblastic leukemia with maturation M4 Acute promyelocytic leukemia (APL) M4 eos Acute myelomonocytic leukemia M5 Acute myelomonocytic leukemia with eosinophilia M6 Acute monocytic leukemia M7 Acute erythroid leukemia Most common AML: MNon-specific ommon AML: M7 . MPO negative AML: M0, M6, M7 . Monocytes leukaemias: M4, M5 . AML with Best prognosis: M2 > M3 . AML associated with DIC: M3 . Most common leukaemia in Down’s syndrome: ALL . Most common AML in Down’s syndrome: M7 . AML causing gum hypertrophy: M5 > M4 . AML causing extramedullary blast proliferation (Chloromas): M2, M4, M5 . AML causing blast infiltrations in the skin (leukaemia cutis): M5, M4 . AML causing Bone marrow fibrosis: M7 . AML with NSE positive: M4, M5 & M3 .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. M3. NSE positive . Option: C. M4. NSE positive . Option: D. M5. NSE positive .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a patient with acute leukaemia, the immunophenotype pattern is CD 19 +ve, CD 10+ve, CD33+ve, and CD 13+ve. He may probably have-", "options": [{"label": "A", "text": "biphenotypic leukaemia", "correct": false}, {"label": "B", "text": "ALL", "correct": true}, {"label": "C", "text": "AML- M2", "correct": false}, {"label": "D", "text": "AML-M0", "correct": false}], "correct_answer": "B. ALL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>ALL In a patient with acute leukaemia, the immunophenotype pattern is CD 19+ve B cell marker CD33+ve Myeloid marker CD 10+ve B cell marker CD 13+ve Myeloid marker It may appear that , as both B cell & Myeloid markers are positive , it is a case of Biphenotypic Leukaemia, but the Myeloid lineage antigens like CD 13, 33 & CD 117 are not specific enough to allow identification of phenotypic/mixed phenotypic Leukaemia , instead, MPO should necessarily be positive . Hence, the diagnosis is B-ALL & not biphenotypic Leukaemia .</p>\n<p><strong>Highyeild:</strong></p><p>Good prognostic markers for B-ALL: Age 1-10 yrs Cytogenetics: Hyperdiploidy t (12;21) TEL-AML t (9; 12) Trisomy 4, 7, 10 Poor prognostic markers for B-ALL: Increase in TLC Increase in bast number < 1 year, > 10 years Lymphadenopathy Hepatosplenomegaly Males CNS involvement Testicular involvement Cytogenetics: Hypodiploidy t (9;22) BCR-ABL +, p190 Infantile leukaemia t (variable;11) MLL translocation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. biphenotypic leukaemia. For diagnosis of biphenotypic leukaemia: MPO +ve along with CD 19+ve, CD 10+ve . Option: C. AML- M2. For diagnosis, MPO should be +ve . Option: D. AML-M0. For diagnosis, MPO should be +ve .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 42 -year old man was referred with a 2-week history of fever, weakness and bleeding gums. Peripheral smear showed pancytopenia. The bone marrow examination revealed 26% blasts, frequently exhibiting Auer rods and mature myeloid cells. An occasional neutrophil with pseudo-Pelger-Huet anomaly was also noted. Which of the following cytochemical stains is most likely to be positive?", "options": [{"label": "A", "text": "TdT", "correct": false}, {"label": "B", "text": "Non-specific esterase", "correct": false}, {"label": "C", "text": "Myeloperoxidase", "correct": true}, {"label": "D", "text": "Toluidine blue", "correct": false}], "correct_answer": "C. Myeloperoxidase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myeloperoxidase Bone marrow examination showing 26% blasts with Auer rods & mature myeloid cells points towards a diagnosis of Acute myeloid leukaemia . Occasional neutrophil with the pseudo-Pelger-Huet anomaly is suggestive of AML with myelodysplasia-related change s, as pseudo-Pelger-Huet neutrophils are dysplastic neutrophils. AML can be diagnosed with myeloperoxidase (MPO) stain .</p>\n<p><strong>Highyeild:</strong></p><p>Blasts or immature cells are large cells with an increase in Nucleus to cytoplasmic ratio (N/C ratio) found in the bone marrow and can be either Myeloblast or Lymohoblast : table,tr,th,td {border:1px solid black;} Myeloblast Lymohoblast ● Moderate cytoplasm. ● Cytoplasmic granules are present. ● Multiple nucleoli present. ● Most characteristic feature: the presence of Auer rods . ● The scant rim of cytoplasm. ● Cytoplasmic granules are absent. ● Nucleoli are absent. Cytochemistry: Myeloperoxidase (MPO) + Sudan Black B + Cytochemistry: Block positivity with Periodic Acid Schiff (PAS) stain . Monoblasts: Non-specific esterase (NSE) + Hairy cell Leukaemia: TRAP + Erythroblasts: Diffuse positivity with PAS T-ALL: TdT +</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. TdT. Positive for T-ALL . Option: B. Non-specific esterase. Positive for Monoblast . Option: D. Toluidine blue. Stain for Basophils .</p>\n<p><strong>Extraedge:</strong></p><p>Good prognostic markers in AML: All these can be diagnosed even if blasts are less than 20% t(8;21) AMLeto RUNX1/RUNX1T1 M2 t(15;17) PML-RARA M3 inv (16) or t(16;16) CBFB-MYH M4 Poor prognostic markers in AML: t (6;9) t (1;22)</p>\n<p><strong>Table:</strong></p><p>WHO classification of AML: 1. AML with recurrent cytogenetic aberration 2. AML therapy related 3. AML with Myelodysplasia 4. AML in Down syndrome (Transient AML M7) 5. AML NOS (Not otherwise specified)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The biochemical marker of acute lymphocytic leukaemia is-", "options": [{"label": "A", "text": "Enolase", "correct": false}, {"label": "B", "text": "Peroxidase", "correct": false}, {"label": "C", "text": "Non-specific esterase", "correct": false}, {"label": "D", "text": "Periodic acid Schiff", "correct": true}], "correct_answer": "D. Periodic acid Schiff", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Periodic acid Schiff Periodic acid Schiff gives block positivity with lymphoblasts , so it is a marker of ALL .</p>\n<p><strong>Highyeild:</strong></p><p>Blasts or immature cells are large cells with an increase in Nucleus to cytoplasmic ratio (N/C ratio) found in the bone marrow and can be either Myeloblast or Lymohoblast : table,tr,th,td {border:1px solid black;} Myeloblast Lymohoblast ● Moderate cytoplasm. ● Cytoplasmic granules are present. ● Multiple nucleoli present. ● Most characteristic feature: the presence of Auer rods . ● The scant rim of cytoplasm. ● Cytoplasmic granules are absent. ● Nucleoli are absent. Cytochemistry: Myeloperoxidase (MPO) + Sudan Black B + Cytochemistry: Block positivity with Periodic Acid Schiff (PAS) stain . Monoblasts: Non-specific esterase (NSE) + Hairy cell Leukaemia: TRAP + Erythroblasts: Diffuse positivity with PAS T-ALL: TdT +</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Enolase. Incorrect . Option: C. Peroxidase. Incorrect . Option: D. Non-specific esterase. Positive in Monoblasts .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Flow cytometry is done on:", "options": [{"label": "A", "text": "Polycythemia", "correct": false}, {"label": "B", "text": "Thrombocytosis", "correct": false}, {"label": "C", "text": "Basophil", "correct": false}, {"label": "D", "text": "Lymphocytes", "correct": true}], "correct_answer": "D. Lymphocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphocytes Flow cytometry is done to detect surface molecules like CD markers on Lymphocytes for the diagnosis of chronic lymphoproliferative disorders Blasts for diagnosis of Acute Leukaemias</p>\n<p><strong>Highyeild:</strong></p><p>CD markers: Cells CD markers Immature CD34 Blast CD 34 Lymphoblast: TdT WBC CD 45 Myeloblast MPO, CD 13, 33, 117 Lymphoid ● B cells: CD19 , 20, 21, 22, 23, 24, CD 10, CD 79a, PAX 5 ● T cells: CD 3 , 1, 2, 4, 5, 6, 7, 8 ● NK cells: CD 16, 56 Monocytes CD 14, 64</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Polycythemia. Incorrect . Option: B. Thrombocytosis. Incorrect . Option: C. Basophil. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Periodic acid Schiff stain shows block positivity in -", "options": [{"label": "A", "text": "Myeloblasts", "correct": false}, {"label": "B", "text": "Lymphoblasts", "correct": true}, {"label": "C", "text": "Monoblasts", "correct": false}, {"label": "D", "text": "Megakaryoblasts", "correct": false}], "correct_answer": "B. Lymphoblasts", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphoblasts Periodic acid Schiff stain shows block positivity in lymphoblasts</p>\n<p><strong>Highyeild:</strong></p><p>Blasts or immature cells are large cells with an increase in Nucleus to cytoplasmic ratio (N/C ratio) found in the bone marrow and can be either Myeloblast or Lymohoblast : table,tr,th,td {border:1px solid black;} Myeloblast Lymohoblast ● Moderate cytoplasm. ● Cytoplasmic granules are present. ● Multiple nucleoli present. ● Most characteristic feature: the presence of Auer rods . ● The scant rim of cytoplasm. ● Cytoplasmic granules are absent. ● Nucleoli are absent. Cytochemistry: Myeloperoxidase (MPO) + Sudan Black B + Cytochemistry: Block positivity with Periodic Acid Schiff (PAS) stain . Monoblasts: Non-specific esterase (NSE) + Hairy cell Leukaemia: TRAP + Erythroblasts: Diffuse positivity with PAS T-ALL: TdT +</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Myeloblasts. Incorrect, MPO +ve, Sudan Black B +ve . Option: C. Monoblasts. Incorrect, NSE +ve . Option: D. Megakaryoblasts. Incorrect , CD 41 +ve, CD 61 +ve .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 26 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Mallory Denk bodies are complex of ubiquitin and:", "options": [{"label": "A", "text": "Keratin 8 & 18", "correct": true}, {"label": "B", "text": "Keratin 5 & 15", "correct": false}, {"label": "C", "text": "Keratin 2 & 12", "correct": false}, {"label": "D", "text": "Keratin 14", "correct": false}], "correct_answer": "A. Keratin 8 & 18", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Keratin 8 & 18 Mallory-Denk bodies: These are usually present as clumped, amorphous, eosinophilic material in ballooned hepatocytes. They are made up of tangled skeins of intermediate filaments such as keratins 8 and 18 in complex with other proteins such as ubiquitin.</p>\n<p><strong>Highyeild:</strong></p><p>Mallory-Denk bodies may be seen: Alcoholic liver disease Non-alcoholic steatohepatitis (NASH) Chronic hepatitis C Primary biliary cirrhosis Wilson's disease Alpha-1 antitrypsin deficiency Glycogen storage disease type IV (Andersen's disease) Autoimmune hepatitis Reye's syndrome Hemochromatosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A liver biopsy from a patient with a history of chronic alcohol abuse shows diffuse micro- and macrovesicular steatosis, Mallory-Denk bodies, and pericellular fibrosis. Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Non-alcoholic fatty liver disease (NAFLD)", "correct": false}, {"label": "B", "text": "Acute viral hepatitis", "correct": false}, {"label": "C", "text": "Alcoholic hepatitis", "correct": true}, {"label": "D", "text": "Primary biliary cholangitis", "correct": false}], "correct_answer": "C. Alcoholic hepatitis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Alcoholic hepatitis The given clinical scenario with the patient’s history of chronic alcohol abuse and liver biopsy showing steatosis is suggestive of Alcoholic liver disease- Alcoholic hepatitis.</p>\n<p><strong>Highyeild:</strong></p><p>Alcoholic Hepatitis A potentially life-threatening complication of chronic alcohol abuse characterized by inflammation and necrosis of hepatocytes in the liver. Pathophysiology : Symptoms : Jaundice, abdominal pain, fever, and malaise. Diagnosis: Elevated liver enzymes, elevated bilirubin, and a decreased albumin-to-globulin ratio. Prognosis: Variable Treatment: Strict abstinence from alcohol, supportive care such as intravenous fluids, and nutrition.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Non-alcoholic fatty liver disease (NAFLD): It is a common condition characterized by hepatic steatosis without significant alcohol consumption. However, this patient has a history of chronic alcohol abuse and the liver biopsy shows features consistent with alcoholic liver disease. Option: B. Acute viral hepatitis: is typically characterized by inflammatory changes in the liver. Still, the presence of micro- and macrovesicular steatosis and Mallory-Denk bodies are not typical findings in acute viral hepatitis. Option: D. Primary biliary cholangitis is a chronic autoimmune condition that affects the small bile ducts within the liver and is not typically associated with the histological features seen in this patient's liver biopsy.</p>\n<p><strong>Extraedge:</strong></p><p>The hallmark of alcoholic hepatitis is hepatocyte injury which is characterized by: Ballooning degeneration Spotty necrosis Polymorphonuclear infiltrate Fibrosis in the perivenular and perisinusoidal space do Disse.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of alcoholic liver disease except:", "options": [{"label": "A", "text": "Hepatic Steatosis", "correct": false}, {"label": "B", "text": "Neutrophilic reaction", "correct": false}, {"label": "C", "text": "Alcoholic steatofibrosis", "correct": false}, {"label": "D", "text": "Lymphocytic infiltrate in portal tract", "correct": true}], "correct_answer": "D. Lymphocytic infiltrate in portal tract", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphocytic infiltrate in portal tract Lymphocytic infiltrate is not a feature of ALD. It is more commonly observed in autoimmune liver diseases such as autoimmune hepatitis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Hepatic Steatosis: It occurs due to the accumulation of fat droplets within hepatocytes, which may cause liver injury and inflammation. Option:B. Neutrophilic reaction: It is a common finding in alcoholic hepatitis, which is a severe form of alcoholic liver disease. The presence of neutrophils in the liver indicates inflammation and damage to the liver tissue. Option:C. Alcoholic steatofibrosis: It is a specific form of alcoholic liver disease that is characterized by the accumulation of fat droplets within hepatocytes and pericellular fibrosis. This condition can progress to cirrhosis, a more severe form of liver disease characterized by irreversible liver scarring.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Alcohol causes all of the following biochemical effects except:", "options": [{"label": "A", "text": "Generate Aldehyde", "correct": false}, {"label": "B", "text": "Produce ROS", "correct": false}, {"label": "C", "text": "Increase glutathione level", "correct": true}, {"label": "D", "text": "Release of bacterial endotoxin from the gut", "correct": false}], "correct_answer": "C. Increase glutathione level", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increase glutathione level Glutathione is a powerful antioxidant that helps to protect cells from oxidative damage . However, alcohol consumption can deplete glutathione levels , rather than increase them.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Generate Aldehyde: Alcohol is metabolized in the liver by the enzyme alcohol dehydrogenase, which converts it into acetaldehyde, a toxic substance that can cause DNA damage and other harmful effects. Option:B. Produce ROS: Alcohol consumption can lead to the production of reactive oxygen species (ROS) in the liver, which can cause oxidative damage to liver cells and tissues. Option:D. Release of bacterial endotoxin from the gut: Alcohol consumption can cause damage to the intestinal lining, leading to the release of bacterial endotoxins into the bloodstream. These endotoxins can trigger an inflammatory response and contribute to liver damage.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is a characteristic feature of Alport syndrome on renal biopsy?", "options": [{"label": "A", "text": "Mesangial hypercellularity", "correct": false}, {"label": "B", "text": "Tubular atrophy and interstitial fibrosis", "correct": false}, {"label": "C", "text": "Thickening and splitting of the GBM", "correct": true}, {"label": "D", "text": "Diffuse global glomerulosclerosis", "correct": false}], "correct_answer": "C. Thickening and splitting of the GBM", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thickening and splitting of the GBM Alport syndrome is a genetic disorder affecting the glomerular basement membrane, resulting in thickening and splitting of the membrane. This leads to progressive renal failure, with features such as hematuria, proteinuria, and eventually end-stage renal disease.</p>\n<p><strong>Highyeild:</strong></p><p>Alport syndrome: It is a genetic disorder characterized by progressive renal failure, sensorineural hearing loss, and ocular abnormalities. It follows all modes of inheritance : The most common being X-linked dominant Cause: Mutations in genes that encode type IV collagen , which is an essential component of basement membranes in the kidney, ear, and eye. (COL4A3, COL4A4, and COL4A5 genes) Renal biopsy: Splitting of the glomerular basement membrane Electron microscopy: Basket-weave appearance IF: No specific immunofluorescence finding in Alport syndrome. Features: Eye problem - Retinopathy, anterior lenticonus, kidney- glomerulonephritis, ear- sensorineural hearing loss Most common manifestation: Gross hematuria</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . Mesangial hypercellularity: It is not a characteristic feature of Alport syndrome on renal biopsy. Mesangial hypercellularity is seen in a variety of glomerular diseases including IgA nephropathy, membranous nephropathy, and lupus nephritis. Option: B. Tubular atrophy and interstitial fibrosis: It is a feature of chronic kidney disease and is not specific to Alport syndrome. Option: D. Diffuse global glomerulosclerosis: It is a feature of end-stage renal disease and is not specific to Alport syndrome.</p>\n<p><strong>Extraedge:</strong></p><p>Mutation in alpha-5 chain of collagen type IV: Alport syndrome Mutation in alpha-3 chain of collagen type IV: Goodpasture syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 45-year-old man has chest pain, night sweat, and cough,on sputum examination mycobacterium bacilli was found and a diagnosis of tuberculosis was made. In chronic tuberculosis which type of amyloidosis is seen?", "options": [{"label": "A", "text": "A beta 2", "correct": false}, {"label": "B", "text": "A beta", "correct": false}, {"label": "C", "text": "AA", "correct": true}, {"label": "D", "text": "Amyloidosis is not seen in TB", "correct": false}], "correct_answer": "C. AA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>AA</p>\n<p><strong>Highyeild:</strong></p><p>Amyloidosis results from the abnormal folding of proteins , which become insoluble, aggregate, and deposit as fibrils in Extracellular tissues . Normally, misfolded proteins are degraded intracellularly in proteasomes , or extracellularly by macrophages . It appears that in amyloidosis, these quality control mechanisms fail , leading to the accumulation of a misfolded protein outside cells . In chronic disease, AA type of amyloidosis is seen. In multiple myeloma AL type of amyloidosis is seen. In chronic renal failure, A beta 2 type of amyloidosis is seen. In Senile cerebral disorders like Alzheimer’s disease, A beta type of amyloidosis is seen.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. A beta 2. It is seen in patients on dialysis for CKD . Option: B. A beta. It is seen in Alzheimer's disease . Option: D: Amyloidosis is not seen in TB. False .</p>\n<p><strong>Table:</strong></p><p>Amyloidosis types: Primary Amyloid Plasma cell disorders due to AL- Light chain amyloid Secondary Amyloid Systemic Hereditary Localized i. Systemic (Generalised) Associated Disease Major Fibril Precursor Protein 1. Light chain Primary Multiple myeloma AL λ Chain 2. Reactive systemic 2° Chronic inflammatory condition AA SAA (Serum Amyloid Associated) 3. Hemodialysis Associated Chronic Renal Failure A β 2 m β 2 Microglobulin ii. Hereditary Associated Disease Major Fibril Precursor Protein Familial Mediterranean fever - AA SAA Familial Amyloid Neuropathy - ATTR Transthyretin Systemic senile Amyloidosis - ATTR Transthyretin iii. Localized. Associated Disease Major Fibril Precursor Protein Senile cerebral AD А β APP Endocrine - Thyroid - Islet of Langerhans Medullary CA Type 2 DM A Cal AIAPP Calcitonin Islet amyloid peptide Isolated Atrial Amyloidosis AANF Atrial Natriuretic Factor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 70-year-old man has bone pain and normocytic normochromic anemia, and on further investigations, Bence Jones protein was found in urine. Which type of amyloidosis can be seen in this patient?", "options": [{"label": "A", "text": "A beta 2", "correct": false}, {"label": "B", "text": "A beta", "correct": false}, {"label": "C", "text": "AA", "correct": false}, {"label": "D", "text": "AL", "correct": true}], "correct_answer": "D. AL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>AL From given clinical data and Bence Jones protein found in urine diagnosis of multiple myeloma is made and amyloid light chain depositio n takes place in this condition and AL type of amyloidosis is seen.</p>\n<p><strong>Highyeild:</strong></p><p>Amyloidosis results from the abnormal folding of proteins , which become insoluble, aggregate, and deposit as fibrils in Extracellular tissues . Diagnosis: The diagnosis of amyloidosis depends on the histologic demonstration of amyloid deposits in tissues. The most common sites biopsied are the kidney when renal manifestations are present, or rectal or gingival tissues in patients suspected of having systemic amyloidosis. In suspected cases of AL amyloidosis, serum, and urine protein electrophoresis and immunoelectrophoresis should be performed.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. A beta 2. It is seen in patients on dialysis for CKD . Option: B. A beta. It is seen in Alzheimer's disease . Option: C. It is seen in chronic inflammatory conditions.</p>\n<p><strong>Extraedge:</strong></p><p>On microscopy: Homogenous Pink deposits Congo red stain: Pinkish red color under ordinary light. Apple green birefringence under polarised light. Thioflavin S stain PAS stain Structure of amyloid. (A) A schematic diagram of an amyloid fiber showing four fibrils (there can be as many as six in each fiber) wound around one another with regularly spaced binding of the Congo red dye. (B) Congo red staining shows apple-green birefringence under polarized light, a diagnostic feature of amyloid. (C) Electron micrograph of 7.5- to 10-nm amyloid fibrils. (From Merlini G, Bellotti V: Molecular mechanisms of amyloidosis, N Engl J Med 349:583–596, 2003, with permission of the Massachusetts Medical Society.)</p>\n<p><strong>Table:</strong></p><p>Amyloidosis types: Primary Amyloid Plasma cell disorders due to AL- Light chain amyloid Secondary Amyloid Systemic Hereditary Localized i. Systemic (Generalised) Associated Disease Major Fibril Precursor Protein 1. Light chain Primary Multiple myeloma AL λ Chain 2. Reactive systemic 2° Chronic inflammatory condition AA SAA (Serum Amyloid Associated) 3. Hemodialysis Associated Chronic Renal Failure A β 2 m β 2 Microglobulin ii. Hereditary Associated Disease Major Fibril Precursor Protein Familial Mediterranean fever - AA SAA Familial Amyloid Neuropathy - ATTR Transthyretin Systemic senile Amyloidosis - ATTR Transthyretin iii. Localized. Associated Disease Major Fibril Precursor Protein Senile cerebral AD А β APP Endocrine - Thyroid - Islet of Langerhans Medullary CA Type 2 DM A Cal AIAPP Calcitonin Islet amyloid peptide Isolated Atrial Amyloidosis AANF Atrial Natriuretic Factor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a case of suspected Amyloidosis preferred site to get a biopsy is:", "options": [{"label": "A", "text": "Skin", "correct": false}, {"label": "B", "text": "Myocardium", "correct": false}, {"label": "C", "text": "Rectal mucosa", "correct": true}, {"label": "D", "text": "Skeletal muscle", "correct": false}], "correct_answer": "C. Rectal mucosa", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rectal mucosa The diagnosis of amyloidosis depends on the histologic demonstration of amyloid deposits in tissues. The most common sites biopsied are the kidney when renal manifestations are present , or rectal or gingival tissues in patients suspected of having systemic amyloidosis . Examination of abdominal fat aspirates stained with Congo red can also be used for the diagnosis of systemic amyloidosis .</p>\n<p><strong>Highyeild:</strong></p><p>Amyloidosis results from the abnormal folding of proteins , which become insoluble, aggregate, and deposit as fibrils in Extracellular tissues . Diagnosis: The diagnosis of amyloidosis depends on the histologic demonstration of amyloid deposits in tissues. The most common sites biopsied are the kidney when renal manifestations are present, or rectal or gingival tissues in patients suspected of having systemic amyloidosis. In suspected cases of AL amyloidosis, serum, and urine protein electrophoresis and immunoelectrophoresis should be performed.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Skin. Incorrect . Option: B. Myocardium. Incorrect . Option: D. Skeletal muscle. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>On microscopy: Homogenous Pink deposits Congo red stain: Pinkish red color under ordinary light. Apple green birefringence under polarised light. Thioflavin S stain PAS stain Structure of amyloid. (A) A schematic diagram of an amyloid fiber showing four fibrils (there can be as many as six in each fiber) wound around one another with regularly spaced binding of the Congo red dye. (B) Congo red staining shows apple-green birefringence under polarized light, a diagnostic feature of amyloid. (C) Electron micrograph of 7.5- to 10-nm amyloid fibrils. (From Merlini G, Bellotti V: Molecular mechanisms of amyloidosis, N Engl J Med 349:583–596, 2003, with permission of the Massachusetts Medical Society.)</p>\n<p><strong>Table:</strong></p><p>Amyloidosis types: Primary Amyloid Plasma cell disorders due to AL- Light chain amyloid Secondary Amyloid Systemic Hereditary Localized i. Systemic (Generalised) Associated Disease Major Fibril Precursor Protein 1. Light chain Primary Multiple myeloma AL λ Chain 2. Reactive systemic 2° Chronic inflammatory condition AA SAA (Serum Amyloid Associated) 3. Hemodialysis Associated Chronic Renal Failure A β 2 m β 2 Microglobulin ii. Hereditary Associated Disease Major Fibril Precursor Protein Familial Mediterranean fever - AA SAA Familial Amyloid Neuropathy - ATTR Transthyretin Systemic senile Amyloidosis - ATTR Transthyretin iii. Localized. Associated Disease Major Fibril Precursor Protein Senile cerebral AD А β APP Endocrine - Thyroid - Islet of Langerhans Medullary CA Type 2 DM A Cal AIAPP Calcitonin Islet amyloid peptide Isolated Atrial Amyloidosis AANF Atrial Natriuretic Factor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about the given renal biopsy slide of a patient suffering from systemic amyloidosis, except", "options": [{"label": "A", "text": "It is a Congo red-stained light microscopic slide", "correct": true}, {"label": "B", "text": "If seen under polarized microscope apple green birefringence is seen", "correct": false}, {"label": "C", "text": "Kidney is the most commonly and most severely affected organ in this disease", "correct": false}, {"label": "D", "text": "Thioflavin S stain is positive in amyloidosis", "correct": false}], "correct_answer": "A. It is a Congo red-stained light microscopic slide", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is a Congo red-stained light microscopic slide This is an electron microscope image in which non-branching fibrils can be seen. Amyloidosis of the kidney is the most common and potentially the most serious form of organ involvement. Grossly, the kidneys may be of normal size and color , or, in advanced cases, they may be shrunken because of ischemia caused by vascular narrowing induced by the deposition of amyloid within arterial and arteriolar walls.</p>\n<p><strong>Highyeild:</strong></p><p>Amyloidosis results from the abnormal folding of proteins , which become insoluble, aggregate, and deposit as fibrils in Extracellular tissues . Diagnosis: The diagnosis of amyloidosis depends on the histologic demonstration of amyloid deposits in tissues. The most common sites biopsied are the kidney when renal manifestations are present, or rectal or gingival tissues in patients suspected of having systemic amyloidosis. In suspected cases of AL amyloidosis, serum, and urine protein electrophoresis and immunoelectrophoresis should be performed.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. If seen under polarized microscope apple green birefringence is seen. Correct . Option: B. The kidney is the most commonly and most severely affected organ in this disease. Correct . Option: D. Thioflavin S stain is positive in amyloidosis. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>On microscopy: Homogenous Pink deposits Congo red stain: Pinkish red color under ordinary light. Apple green birefringence under polarised light. Thioflavin S stain PAS stain Structure of amyloid. (A) A schematic diagram of an amyloid fiber showing four fibrils (there can be as many as six in each fiber) wound around one another with regularly spaced binding of the Congo red dye. (B) Congo red staining shows apple-green birefringence under polarized light, a diagnostic feature of amyloid. (C) Electron micrograph of 7.5- to 10-nm amyloid fibrils. (From Merlini G, Bellotti V: Molecular mechanisms of amyloidosis, N Engl J Med 349:583–596, 2003, with permission of the Massachusetts Medical Society.)</p>\n<p><strong>Table:</strong></p><p>Amyloidosis types: Primary Amyloid Plasma cell disorders due to AL- Light chain amyloid Secondary Amyloid Systemic Hereditary Localized i. Systemic (Generalised) Associated Disease Major Fibril Precursor Protein 1. Light chain Primary Multiple myeloma AL λ Chain 2. Reactive systemic 2° Chronic inflammatory condition AA SAA (Serum Amyloid Associated) 3. Hemodialysis Associated Chronic Renal Failure A β 2 m β 2 Microglobulin ii. Hereditary Associated Disease Major Fibril Precursor Protein Familial Mediterranean fever - AA SAA Familial Amyloid Neuropathy - ATTR Transthyretin Systemic senile Amyloidosis - ATTR Transthyretin iii. Localized. Associated Disease Major Fibril Precursor Protein Senile cerebral AD А β APP Endocrine - Thyroid - Islet of Langerhans Medullary CA Type 2 DM A Cal AIAPP Calcitonin Islet amyloid peptide Isolated Atrial Amyloidosis AANF Atrial Natriuretic Factor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "This is the kidney biopsy of a patient who presented with proteinuria being seen after special staining. Which one of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Microscopic polyangiitis", "correct": false}, {"label": "B", "text": "Multiple myeloma", "correct": true}, {"label": "C", "text": "Diabetic nephropathy", "correct": false}, {"label": "D", "text": "Good Pasture's syndrome", "correct": false}], "correct_answer": "B. Multiple myeloma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686826405688-QTDP049006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple myeloma In the given image, Amyloid deposits can be seen indicating Multiple myeloma . The special stain used here is Congo red stain which under polarised light gives Apple green birefringence in amyloidosis . The malignant plasma cells synthesize abnormal amounts of a single Ig (monoclonal gammopathy), producing an M (myeloma) protein spike on serum electrophoresis .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features: Hyper C alcemia R enal failure A nemia B one disease Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Microscopic polyangiitis. Microscopic polyangiitis is a systemic vasculitis that predominantly affects the small blood vessels , and is associated with P-ANCA, doesn’t show Apple green birefringence with Congo Red stain . Option: C. Diabetic nephropathy. Diabetic nephropathy is a common complication of type 1 and type 2 diabetes . Over time, poorly controlled diabetes can cause damage to blood vessels in the kidneys. It presents with proteinuria but doesn’t show Apple green birefringence with Congo Red stain . Option: D. Goodpasture syndrome. Goodpasture syndrome also referred to as anti-glomerular basement membrane (anti-GBM) disease , is an autoimmune disease that affects both the kidneys and lungs by the formation of autoantibodies that attack their basement membranes. It presents with proteinuria but doesn’t show Apple green birefringence with Congo Red stain .</p>\n<p><strong>Extraedge:</strong></p><p>It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mark the false statement:", "options": [{"label": "A", "text": "AL has a kappa light chain", "correct": false}, {"label": "B", "text": "SAA is most common in Mediterranean fever", "correct": false}, {"label": "C", "text": "Senile amyloidosis is due to β2-m microglobulin", "correct": true}, {"label": "D", "text": "On Congo Red staining, amyloid shows apple green birefringence", "correct": false}], "correct_answer": "C. Senile amyloidosis is due to β2-m microglobulin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Senile amyloidosis is due to β2-m microglobulin Senile amyloidosis is due to Aβ type of amyloidosis Hemodialysis-associated Amyloidosis is due to the Aβ2-m type of amyloidosis .</p>\n<p><strong>Highyeild:</strong></p><p>Amyloidosis results from the abnormal folding of proteins , which become insoluble, aggregate, and deposit as fibrils in Extracellular tissues . Normally, misfolded proteins are degraded intracellularly in proteasomes , or extracellularly by macrophages . It appears that in amyloidosis, these quality control mechanisms fail , leading to the accumulation of a misfolded protein outside cells . Classification of Amyloidosis Clinicopathologic Category Associated Diseases Major Fibril Protein Chemically Related Precursor Protein Systemic (Generalized) Amyloidosis Immunoglobulin light chain amyloidosis (primary amyloidosis) Multiple myeloma and other monoclonal plasma cell proliferations AL Immunoglobulin light chains, chiefly λ type Reactive systemic amyloidosis (secondary amyloidosis) Chronic inflammatory conditions AA SAA Hemodialysis-associated amyloidosis Chronic renal failure Aβ 2 m β 2 -microglobulin Hereditary Amyloidosis Familial Mediterranean fever AA SAA Familial amyloidotic neuropathies (several types) ATTR Transthyretin Systemic senile amyloidosis ATTR Transthyretin Localized Amyloidosis Senile cerebral Alzheimer disease Аβ APP Endocrine Medullary carcinoma of thyroid Islets of Langerhans Type 2 diabetes A Cal AIAPP Calcitonin Islet amyloid peptide Isolated atrial amyloidosis AANF Atrial natriuretic factor In chronic disease, AA type of amyloidosis is seen. In multiple myeloma AL type of amyloidosis is seen. In chronic renal failure, A beta 2 type of amyloidosis is seen. In Senile cerebral disorders like Alzheimer’s disease, A beta type of amyloidosis is seen.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. AL has a kappa light chain. True . Option: B. SAA is most common in Mediterranean fever. True . Option: D. On Congo Red staining, amyloid shows apple-green birefringence. True .</p>\n<p><strong>Table:</strong></p><p>Amyloidosis types: Primary Amyloid Plasma cell disorders due to AL- Light chain amyloid Secondary Amyloid Systemic Hereditary Localized i. Systemic (Generalised) Associated Disease Major Fibril Precursor Protein 1. Light chain Primary Multiple myeloma AL λ Chain 2. Reactive systemic 2° Chronic inflammatory condition AA SAA (Serum Amyloid Associated) 3. Hemodialysis Associated Chronic Renal Failure A β 2 m β 2 Microglobulin ii. Hereditary Associated Disease Major Fibril Precursor Protein Familial Mediterranean fever - AA SAA Familial Amyloid Neuropathy - ATTR Transthyretin Systemic senile Amyloidosis - ATTR Transthyretin iii. Localized. Associated Disease Major Fibril Precursor Protein Senile cerebral AD А β APP Endocrine - Thyroid - Islet of Langerhans Medullary CA Type 2 DM A Cal AIAPP Calcitonin Islet amyloid peptide Isolated Atrial Amyloidosis AANF Atrial Natriuretic Factor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding abdominal aorta aneurysms except :", "options": [{"label": "A", "text": "Most favoured site for aneurysm generation by atherosclerotic region", "correct": false}, {"label": "B", "text": "More common in males and smokers", "correct": false}, {"label": "C", "text": "Most of these are asymptomatic and incidentally detected", "correct": false}, {"label": "D", "text": "Tendency of rupture does not correlate with the size of the aneurysm", "correct": true}], "correct_answer": "D. Tendency of rupture does not correlate with the size of the aneurysm", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tendency of rupture does not correlate with the size of the aneurysm Most cases of A bdominal Aorta Aneurysm (AAA) are asymptomatic and are discovered incidentally on a physical exam as an abdominal mass. AAAs occur more frequently in men and smokers , rarely developing before age 50 . Atherosclerosis is a major cause of AAA , but other factors contribute since the incidence is less than 5% in men older than age 60 years.</p>\n<p><strong>Highyeild:</strong></p><p>An aneurysm is a localized abnormal dilation of a blood vessel or the heart that may be congenital or acquired . When an aneurysm involves all the layers of an intact (but attenuated) arterial wall or the thinned ventricular wall of the heart, it is called a true aneurysm . A false aneurysm (also called a pseudoaneurysm ) is a defect in the vascular wall leading to an extravascular hematoma that freely communicates with the intravascular space (“ pulsating hematoma ”). The two most important causes of aortic aneurysms are atherosclerosis and hypertension ; atherosclerosis is a greater factor in AAAs, while hypertension is the most common etiology associated with ascending aortic aneurysms. Most cases of Abdominal Aorta Aneurysm (AAA) are asymptomatic and are discovered incidentally on physical exam as an abdominal mass. The other clinical manifestations of AAAs include: Rupture into the peritoneal cavity or retroperitoneal tissues with massive, potentially fatal haemorrhage. Obstruction of a branch vessel results in downstream tissue ischemic injury; for example, iliac (leg), renal (kidney), mesenteric (gastrointestinal tract), or vertebral arteries (spinal cord). Embolism from atheroma or mural thrombus. Impingement on an adjacent structure, for example, compression of a ureter or erosion of vertebrae. A patient with an AAA is also very likely to have atherosclerosis in other vascular beds and is at a significantly increased risk of ischemic heart disease and stroke .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Most favoured site for aneurysm generation by atherosclerotic region. Correct . Option: B. More common in males and smokers. Correct . Option: D. Most of these are asymptomatic and incidentally detected. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Risk Factors For The Development Of AAA. Smoking Hypertension High cholesterol levels Atherosclerotic disease Male gender Increasing age Inflammatory (eg, Takayasu's arteritis) and infectious (eg, mycotic) aortitis and the presence of an underlying aortic dissection Penetrating atherosclerotic ulcer Intramural hematoma Inherited genetic defects of the connective tissue (eg, Turner syndrome, Ehlers-Danlos syndrome)</p>\n<p><strong>Table:</strong></p><p>Indication for intervention in aortic aneurysm: 1. Symptomatic irrespective of\nsize. 2. Asymptomatic (based on size\nand rate of increase in size). a. Ascending aorta ≥ 5.5 cm, rate of change > 0.5\ncm/yr. b. Abdominal aorta females: ≥ 5.5cm, males ≥ 4.5-5 cm,\nrate of change > 1 cm/yr. c. Descending aorta ≥ 6 cm, rate of change > 1\ncm/yr. Screening of rate of change: USG .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding inflammatory abdominal aorta aneurysms except :", "options": [{"label": "A", "text": "Usually seen in old-age", "correct": true}, {"label": "B", "text": "Patient presents with back pain and elevated CRP", "correct": false}, {"label": "C", "text": "Histologically there is lymphoplasmacytic infiltrate and macrophages", "correct": false}, {"label": "D", "text": "Most of the patients don’t have associated inflammation of other arteries", "correct": false}], "correct_answer": "A. Usually seen in old-age", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Usually seen in old-age Inflammatory Abdominal Aorta Aneurysm accounts for 5% to 10% of all AAA; these typically occur in younger patients , who often present with back pain and elevated inflammatory markers (g.: elevation of C-reactive protein). Inflammatory aneurysms are characterized by abundant lymphoplasmacytic inflammation with many macrophages (and even giant cells) associated with dense periaortic scarring that can extend into the anterior retroperitoneum. The cause is a presumed localized immune response to the abdominal aortic wall; remarkably, most cases are not associated with inflammation of other arteries .</p>\n<p><strong>Highyeild:</strong></p><p>An aneurysm is a localized abnormal dilation of a blood vessel or the heart that may be congenital or acquired . When an aneurysm involves all the layers of an intact (but attenuated) arterial wall or the thinned ventricular wall of the heart, it is called a true aneurysm . A false aneurysm (also called a pseudoaneurysm ) is a defect in the vascular wall leading to an extravascular hematoma that freely communicates with the intravascular space (“ pulsating hematoma ”). The two most important causes of aortic aneurysms are atherosclerosis and hypertension ; atherosclerosis is a greater factor in AAAs, while hypertension is the most common etiology associated with ascending aortic aneurysms. Most cases of Abdominal Aorta Aneurysm (AAA) are asymptomatic and are discovered incidentally on physical exam as an abdominal mass. The other clinical manifestations of AAAs include: Rupture into the peritoneal cavity or retroperitoneal tissues with massive, potentially fatal haemorrhage. Obstruction of a branch vessel results in downstream tissue ischemic injury; for example, iliac (leg), renal (kidney), mesenteric (gastrointestinal tract), or vertebral arteries (spinal cord). Embolism from atheroma or mural thrombus. Impingement on an adjacent structure, for example, compression of a ureter or erosion of vertebrae. A patient with an AAA is also very likely to have atherosclerosis in other vascular beds and is at a significantly increased risk of ischemic heart disease and stroke .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. The patient presents with back pain and elevated CRP. Correct . Option: C. Histologically there is lymphoplasmacytic infiltrate and macrophages. Correct . Option: D. Most of the patients don’t have associated inflammation of other arteries. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Risk Factors For The Development Of AAA. Smoking Hypertension High cholesterol levels Atherosclerotic disease Male gender Increasing age Inflammatory (eg, Takayasu's arteritis) and infectious (eg, mycotic) aortitis and the presence of an underlying aortic dissection Penetrating atherosclerotic ulcer Intramural hematoma Inherited genetic defects of the connective tissue (eg, Turner syndrome, Ehlers-Danlos syndrome)</p>\n<p><strong>Table:</strong></p><p>Indication for intervention in aortic aneurysm: 1. Symptomatic irrespective of size. 2. Asymptomatic (based on size and rate of increase in size). a. Ascending aorta ≥ 5.5 cm, rate of change > 0.5 cm/yr. b. Abdominal aorta females: ≥ 5.5cm, males ≥ 4.5-5 cm, rate of change > 1 cm/yr. c. Descending aorta ≥ 6 cm, rate of change > 1 cm/yr. Screening of rate of change: USG .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mutations in TGF-β receptors lead to defective synthesis of elastin and collagens I and III leading to aneurysms in which syndrome?", "options": [{"label": "A", "text": "Marfan syndrome", "correct": false}, {"label": "B", "text": "Ehlers-Danlos syndrome", "correct": false}, {"label": "C", "text": "Loeys-Dietz syndrome", "correct": true}, {"label": "D", "text": "Churg strauss syndrome", "correct": false}], "correct_answer": "C. Loeys-Dietz syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Loeys-Dietz syndrome Loeys-Dietz syndrome is another cause of aneurysms; in this disorder, mutations in TGF-β receptor s lead to defective synthesis of elastin and collagens I and III . Aneurysms in such individuals can rupture fairly easily ( even at small size s ) and are thus considered to follow an “ aggressive” course .</p>\n<p><strong>Highyeild:</strong></p><p>Defects in the synthesis or breakdown of connective tissue contribute to the pathobiology of both heritable aneurysmal diseases, as well as the common, sporadic forms of aneurysms. These defects include the following: The intrinsic quality of the vascular wall connective tissue is poor. Weak vessel walls due to defective type III collagen synthesis are a hallmark of the vascular form of Ehlers-Danlos syndrome . Abnormal transforming growth factor-β (TGF-β) signalling . Excessive TGF-β activity alters vascular wall remodelling, primarily of the ascending aorta, leading ultimately to diminished ECM content and integrity with aneurysmal dilation. In Marfan syndrome , defective synthesis of the scaffolding protein fibrillin leads to the inability to appropriately sequester endogenously produced TGF-β. In Loeys-Dietz syndrome , increased activity in the TGF-β signalling pathway can result from mutations in TGF-β receptors , an intracellular downstream signalling molecule in the TGF-β pathway (SMAD3), and even TGF-β3 itself. Aneurysms in patients with Loeys-Dietz syndrome can rupture at small sizes and are thus considered to follow an “aggressive” course . The balance of collagen degradation and synthesis is altered by inflammation and associated proteases . Inflammatory cells in the setting of an aortitis or associated with atherosclerosis can be found throughout the aortic wall. Increased MMP production, especially by macrophages, can contribute to aneurysm development by degrading ECM (elastin, collagens, proteoglycans, laminin, fibronectin) in all layers of the wall; decreased expression of TIMPs can also impact ECM degradation. Both processes result in a loss of elastic fibres necessary for recoil in diastole. The vascular wall is weakened through the loss of smooth muscle cells or the inappropriate synthesis of noncollagenous or nonelastic ECM . Ischemia of the inner media occurs when there is an atherosclerotic thickening of the intima, increasing the distance that oxygen and nutrients must diffuse. Systemic hypertension can also cause significant narrowing of arterioles of the vasa vasorum (e.g., in the aorta), which causes outer medial ischemia. Tertiary syphilis is another rare cause of aortic aneurysms in which obliterative endarteritis occurs in the vasa vasorum of the thoracic aorta; this engenders medial ischemia that leads to smooth muscle cell loss, elastic fibre loss, and inadequate or inappropriate ECM synthesis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Marfan syndrome. Incorrect, defective synthesis of the scaffolding protein fibrillin . Option: B. Ehlers-Danlos syndrome. Incorrect , defective type III collagen synthesis . Option: D. Churg strauss syndrome. Incorrect .</p>\n<p><strong>Table:</strong></p><p>Indication for intervention in aortic aneurysm: 1. Symptomatic irrespective of size. 2. Asymptomatic (based on size and rate of increase in size). a. Ascending aorta ≥ 5.5 cm, rate of change > 0.5 cm/yr. b. Abdominal aorta females: ≥ 5.5cm, males ≥ 4.5-5 cm, rate of change > 1 cm/yr. c. Descending aorta ≥ 6 cm, rate of change > 1 cm/yr. Screening of rate of change: USG .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding mycotic aneurysms except:", "options": [{"label": "A", "text": "Most common causative organism is a fungus", "correct": true}, {"label": "B", "text": "It can be a complication of infective endocarditis", "correct": false}, {"label": "C", "text": "It can be an extension of an adjacent suppurative process", "correct": false}, {"label": "D", "text": "Can originate from circulating organisms directly infecting the arterial wall", "correct": false}], "correct_answer": "A. Most common causative organism is a fungus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Most common causative organism is a fungus False, the most common pathogens are Staphylococcus aureus Mycotic aneurysms can originate from: From embolization of a septic embolus , usually as a complication of infective endocarditis. As an extension of an adjacent suppurative process . By circulating organisms directly infecting the arterial wall.</p>\n<p><strong>Highyeild:</strong></p><p>Mycotic Aneurysm: A mycotic aneurysm is an infection of a vessel wall which can be bacterial, fungal, or viral in origin . It does not refer to fungal etiology , as the majority of infected aneurysms are caused by bacterial pathogens . Therefore the correct term for these aneurysms can be an infected aneurysm. Infectious aortitis refers to vessel infection without aneurysmal dilation . The risks are higher in immune-compromised hostse., HIV, diabetes, high-dose glucocorticoids , or malignancy/chemotherapy . Commonly involved vessels are femoral , followed by the aorta, then intracranial visceral (e.g., superior mesenteric, splenic) arteries. The most common manifestations are fever, pulsatile mass, local pain, and inflammation in the arterial site (back pain in the aorta, and headaches in intracranial vessels). Due to the non-specific nature of these signs, many patients are evaluated as having a fever of unknown origin and remain undiagnosed until there are severe symptoms of sepsis, thrombosis, haemorrhage, or rupture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. It can be a complication of infective endocarditis. Correct . Option: C. It can be an extension of an adjacent suppurative process. Correct . Option: D. Can originate from circulating organisms directly infecting the arterial wall. Correct .</p>\n<p><strong>Table:</strong></p><p>Indication for intervention in aortic aneurysm: 1. Symptomatic irrespective of size. 2. Asymptomatic (based on size and rate of increase in size). a. Ascending aorta ≥ 5.5 cm, rate of change > 0.5 cm/yr. b. Abdominal aorta females: ≥ 5.5cm, males ≥ 4.5-5 cm, rate of change > 1 cm/yr. c. Descending aorta ≥ 6 cm, rate of change > 1 cm/yr. Screening of rate of change: USG .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding aortic dissection except:", "options": [{"label": "A", "text": "Hypertension is the most common cause", "correct": false}, {"label": "B", "text": "Intimal tear is the initial event to occur", "correct": false}, {"label": "C", "text": "Absence of widening of the aortic silhouette on Chest X-Ray rules out Aortic dissection", "correct": true}, {"label": "D", "text": "Stanford type B requires medical management", "correct": false}], "correct_answer": "C. Absence of widening of the aortic silhouette on Chest X-Ray rules out Aortic dissection", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Absence of widening of the aortic silhouette on Chest X-Ray rules out Aortic dissection False, While the widening of the aortic silhouette on Chest X-Ray increases the likelihood of Aortic Dissection, its absence does not reliably exclude the diagnosis .</p>\n<p><strong>Highyeild:</strong></p><p>Aortic dissection: Aortic dissection occurs when blood separates the laminar planes of the media to form a blood-filled channel within the aortic wall . Aortic dissection occurs principally in two groups of patients: Men aged 40 to 60 years , with antecedent hypertension (more than 90% of cases) Younger patients with syndromic diseases affecting the aorta (e.g.: Marfan syndrome). Dissections can be iatrogenic (e.g., following arterial cannulations during diagnostic catheterization or cardiopulmonary bypass). Hypertension is the major risk factor for aortic dissection. Aortic dissection usually initiates with an intimal tear . In the vast majority of spontaneous dissections, the tear occurs in the ascending aorta, usually within 10 cm of the aortic valve. The dissecting hematoma spreads characteristically between lamellar units of the outer third of the media or between media and adventitial layers . The Stanford system is more frequently employed. It classifies dissections into two types based on whether the ascending or descending part of the aorta is involved. Type A involves the ascending aorta , regardless of the site of the primary intimal tear. Type A dissection is defined as a dissection proximal to the brachiocephalic artery . This requires surgical management . Type B aortic dissection originating distal to the left subclavian artery and involving only descending aorta. This requires medical management . This involves administering short-acting IV beta-blockers aiming for a heart rate of ~60 bpm (reductions in heart rate and blood pressure reduces aortic wall tension and limit the extent of dissection). While the widening of the aortic silhouette on Chest X-Ray increases the likelihood of Aortic Dissection, its absence does not reliably exclude the diagnosis . If the patient is stable , a CT scan with contrast is recommended. For unstable patients, TransEsophageal Echocardiogram/TEE is the preferred procedure. Once the tear has occurred, blood flow under systemic pressure dissects through the media leading to the progression of the hematoma. Accordingly, aggressive pressure-reducing therapy may be effective in limiting an evolving dissection .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hypertension is the most common cause. Correct . Option: B. Intimal tear is the initial event to occur. Correct . Option: D. Stanford type B requires medical management. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Dissection is unusual in the presence of substantial atherosclerosis or other cause of medial scarrings, such as syphilis , presumably because the medial fibrosis inhibits propagation of the dissecting hematoma .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding clinical features of aortic dissection except:", "options": [{"label": "A", "text": "Presents with sudden onset of excruciating pain, usually beginning in the anterior chest, radiating to the back", "correct": false}, {"label": "B", "text": "It is classified into two types A and B, based on involvement Of ascending aorta", "correct": false}, {"label": "C", "text": "Most common cause of death is rupture of the dissection into the pericardial, pleural, or peritoneal cavities", "correct": false}, {"label": "D", "text": "Recognizable medial degeneration is a prerequisite for dissection and a reliable predictor of its occurrence", "correct": true}], "correct_answer": "D. Recognizable medial degeneration is a prerequisite for dissection and a reliable predictor of its occurrence", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Recognizable medial degeneration is a prerequisite for dissection and a reliable predictor of its occurrence False, recognizable medial degeneration appears to be neither a prerequisite for dissection nor a reliable predictor of its occurrence .</p>\n<p><strong>Highyeild:</strong></p><p>Aortic dissection: Aortic dissection occurs when blood separates the laminar planes of the media to form a blood-filled channel within the aortic wall . Aortic dissection occurs principally in two groups of patients: Men aged 40 to 60 years , with antecedent hypertension (more than 90% of cases) Younger patients with syndromic diseases affecting the aorta (e.g.: Marfan syndrome). Dissections can be iatrogenic (e.g., following arterial cannulations during diagnostic catheterization or cardiopulmonary bypass). Hypertension is the major risk factor for aortic dissection. Aortic dissection usually initiates with an intimal tear . In the vast majority of spontaneous dissections, the tear occurs in the ascending aorta, usually within 10 cm of the aortic valve. The dissecting hematoma spreads characteristically between lamellar units of the outer third of the media or between media and adventitial layers . The Stanford system is more frequently employed. It classifies dissections into two types based on whether the ascending or descending part of the aorta is involved. Type A involves the ascending aorta , regardless of the site of the primary intimal tear. Type A dissection is defined as a dissection proximal to the brachiocephalic artery . This requires surgical management . Type B aortic dissection originating distal to the left subclavian artery and involving only descending aorta. This requires medical management . This involves administering a short-acting IV beta-blockers aiming for a heart rate of ~60 bpm (reductions in heart rate and blood pressure reduces aortic wall tension and limit the extent of dissection). While the widening of the aortic silhouette on Chest X-Ray increases the likelihood of Aortic Dissection, its absence does not reliably exclude the diagnosis . If the patient is stable , a CT scan with contrast is recommended. For unstable patients, TransEsophageal Echocardiogram/TEE is the preferred procedure. Once the tear has occurred, blood flow under systemic pressure dissects through the media leading to the progression of the hematoma. Accordingly, aggressive pressure-reducing therapy may be effective in limiting an evolving dissection .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Presents with sudden onset of excruciating pain, usually beginning in the anterior chest, radiating to the back. Correct . Option: B. It is classified into two types A and B, based on the involvement of ascending aorta. Correct . Option: C. A most common cause of death is rupture of the dissection into the pericardial, pleural, or peritoneal cavities. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Dissection is unusual in the presence of substantial atherosclerosis or other cause of medial scarrings, such as syphilis , presumably because the medial fibrosis inhibits propagation of the dissecting hematoma .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Natural killer cells attack which of the following cells?", "options": [{"label": "A", "text": "Cells that express MHC 1", "correct": false}, {"label": "B", "text": "Cells that are not able to express MHC 1", "correct": true}, {"label": "C", "text": "MHC cells which express MHC 2", "correct": false}, {"label": "D", "text": "Cells which are not able to express MHC 2", "correct": false}], "correct_answer": "B. Cells that are not able to express MHC 1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cells that are not able to express MHC 1 NK cell inhibitory receptors recognize self-class I MHC molecules , which are expressed in all healthy cells . The inhibitory receptors prevent NK cells from killing normal cells . Virus infection or neoplastic transformation often enhances the expression of ligands for activating receptors and at the same time reduces the expression of class I MHC molecules . As a result, the balance is tilted toward activation, and the infected or tumor cell is killed .</p>\n<p><strong>Highyeild:</strong></p><p>Natural Killer cells The function of NK cells is to recognize and destroy severely stressed or abnormal cells , such as virus-infected cells and tumor cells . NK cells make up approximately 5% to 10% of peripheral blood lymphocytes . NK cells express CD16, a receptor for IgG Fc tails that confers on NK cells the ability to lyse IgG-coated target cells . This phenomenon is known as antibody-dependent cellular cytotoxicity (ADCC) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cells that express MHC 1. Incorrect . Option: C. MHC cells that express MHC 2. Incorrect . Option: D. Cells that are not able to express MHC 2. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Most potent stimulator of naïve T-cells:", "options": [{"label": "A", "text": "Mature dendritic cells", "correct": true}, {"label": "B", "text": "Follicular dendritic cells", "correct": false}, {"label": "C", "text": "Macrophages", "correct": false}, {"label": "D", "text": "B-cell", "correct": false}], "correct_answer": "A. Mature dendritic cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mature dendritic cells Antigen-presenting cells (APCs) capture microbes and other antigens , transport them to secondary lymphoid organs , and display them for recognition by lymphocytes . The most efficient APCs are dendritic cells (DCs) , which are present in epithelia and most other tissues. Integrins are adhesion molecules that promote the attachment of T-cells to APCs . They express high levels of MHC and other molecules needed for presenting antigens to and activating T cells .</p>\n<p><strong>Highyeild:</strong></p><p>Antigen Presenting Cells: Cells that identify, process, and present Ag to T cells . Signals: from APC to T cells a.MHC presenting Ag to TCR b. CD 80/86 activating CD 28 c. Specific cytokines from APC to T cells</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Follicular dendritic cells. A second type of cell with dendritic morphology is present in the germinal centers of lymphoid follicles in the spleen and lymph nodes and is called the follicular dendritic cell (FDC) . They play a role in humoral immune respons es by presenting antigens to B cells in the germinal center , part of a process through which only B cells that express antibodies with high affinity for antigen survive and go on to mature into plasma cells or memory cells Option: C. Macrophages that have phagocytosed microbes and protein antigens process the antigens and present peptide fragments to T cells. Thus, macrophages function as antigen-presenting cells in T-cell activation. Option: D. B-cell. Membrane-bound antibodies of the IgM and IgD isotypes , present on the surface of all mature, naïve B cells, are the antigen-binding component of the B-cell receptor (BCR) complex</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "True about MHC class II –", "options": [{"label": "A", "text": "Involved in innate immunity", "correct": false}, {"label": "B", "text": "Cytotoxic T-cell involved", "correct": false}, {"label": "C", "text": "Present in nucleated cells", "correct": false}, {"label": "D", "text": "Present in B-cells", "correct": true}], "correct_answer": "D. Present in B-cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Present in B-cells</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted. In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Involved in innate immunity. False, MHC II is associated with adaptive immunity . Option: B. Cytotoxic T-cell involved. Helper T cells/ CD 4+ T cells are MHC II restricted . Option: C. Present in nucleated cells. MHC II is present in all Antigen Presenting Cells (APCs) .</p>\n<p><strong>Table:</strong></p><p>MHC I VS MHC II</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which statement given below is not true about professional APCs?", "options": [{"label": "A", "text": "Professional APCs express both MHC I and MHC II", "correct": false}, {"label": "B", "text": "It has an unlimited capacity to identify antigens", "correct": false}, {"label": "C", "text": "Dendritic cells in lymph nodes are an example", "correct": false}, {"label": "D", "text": "None of the above", "correct": true}], "correct_answer": "D. None of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above Antigen-presenting cells (APCs) capture microbes and other antigens, transport them to secondary lymphoid organs , and display them for recognition by lymphocytes. The most efficient APCs are dendritic cells (DCs) , which are present in epithelia and most other tissues. There are two types of APCs: Professionals Non- professional APCs.</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Professional APCs express both MHC I and MHC II. True , as Professional APCs contain a nucleus thus express MHC I, and MHC II are expressed on APCs. Option: B. It has unlimited capacity to identify antigens. True . Option: C. Dendritic cells in lymph nodes are an example. True .</p>\n<p><strong>Extraedge:</strong></p><p>In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Gene for Major Histocompatibility Complex is present on-", "options": [{"label": "A", "text": "6p", "correct": true}, {"label": "B", "text": "6q", "correct": false}, {"label": "C", "text": "16p", "correct": false}, {"label": "D", "text": "16q", "correct": false}], "correct_answer": "A. 6p", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>6p MHC molecules were discovered as products of genes that evoke rejection of transplanted organs, and their name derives from their role in determining tissue compatibility between individuals .</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted . In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. 6q. Incorrect . Option: C. 16p. Incorrect . Option: D. 16q. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are false regarding MHC I except-", "options": [{"label": "A", "text": "It presents extracellular antigen", "correct": false}, {"label": "B", "text": "It encodes HLA A, HLA B, and HLA C", "correct": true}, {"label": "C", "text": "It is present in all anucleated cells", "correct": false}, {"label": "D", "text": "It presents antigen to CD4 T lymphocytes", "correct": false}], "correct_answer": "B. It encodes HLA A, HLA B, and HLA C", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It encodes HLA A, HLA B, and HLA C</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted . In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It presents an extracellular antigen. False, it presents intracellular antigen . Option: C. It is present on all anucleated cells. False, Class I MHC molecules are expressed on all nucleated cells and platelets . Option: D. It presents antigen to CD4 T lymphocytes. Class I MHC molecules display peptides that are derived from cytoplasmic proteins, including normal proteins and virus- and tumor-specific antigens , which are all recognized and bound to class I MHC molecules by CD8+ T cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is correct regarding MHC II?", "options": [{"label": "A", "text": "It encodes DP, DQ, and DR", "correct": false}, {"label": "B", "text": "Presents extracellular antigen to CD 4 T cells", "correct": false}, {"label": "C", "text": "It is present in Antigen-presenting cells", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted . In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It encodes DP, DQ, DR. True . Option: B. Presents extracellular antigen to CD 4 T cells. True . Option: C. It is present on Antigen-presenting cells. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Antigen-presenting cells stimulate T cells by-", "options": [{"label": "A", "text": "MHC", "correct": false}, {"label": "B", "text": "Cytokines released depend on the type of antigen exposure", "correct": false}, {"label": "C", "text": "B7 proteins", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Naïve T lymphocytes are activated by antigen and costimulators in peripheral lymphoid organs , and proliferate and differentiate into effector cells that migrate to any site where microbial antigens are present.</p>\n<p><strong>Highyeild:</strong></p><p>Major Histocompatibility Complex (MHC): The function of Major Histocompatibility Complex (MHC) molecules is to display peptide fragments of protein antigens for recognition by antigen-specific T cells . In humans, the MHC molecules are called human leukocyte antigens (HLA) because they were initially detected in leukocytes. The genes encoding HLA molecules are clustered on a small segmen t of chromosome 6 . Because CD4+ T cells can recognize antigens only in the context of self-class II molecules, they are referred to as class II MHC restricted . In contrast to class I molecules, class II MHC molecules are mainly expressed on cells that present ingested antigens (Antigen-presenting Cells) and respond to T-cell help ( macrophages, B lymphocytes, and dendritic cells ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. MHC. Class II MHC molecules present antigens derived from extracellular microbes and proteins following their internalization into endosomes or lysosomes. Class I MHC molecules display peptides that are derived from cytoplasmic proteins, including normal proteins and virus - and tumor-specific antigens , which are all recognized and bound to class I MHC molecules by CD8+ T cells. Option: B. Cytokines released depend on the type of antigen exposure. Some of the activated CD4+ T cells differentiate into effector cells that secrete distinct sets of cytokines and perform different functions. Option: C. B7 proteins. The principal costimulators for T cells are the B7 proteins (CD80 and CD86) that are expressed on antigen-presenting cells and are recognized by the CD28 receptor on naïve T cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All are true regarding apoptosis except:", "options": [{"label": "A", "text": "Chromatin is lysed by endonucleases to form nucleosome", "correct": false}, {"label": "B", "text": "It initiates local inflammatory reactions", "correct": true}, {"label": "C", "text": "Macrophages phagocytose remaining apoptotic bodies", "correct": false}, {"label": "D", "text": "Caspases are increased and mediates apoptosis", "correct": false}], "correct_answer": "B. It initiates local inflammatory reactions", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It initiates local inflammatory reactions Apoptosis is a pathway of programmed cell death in which cells activate enzymes that degrade the cells’ own nuclear DNA and nuclear and cytoplasmic proteins . The plasma membrane of the apoptotic cell remains intact , but the membrane is altered in such a way that the cell and its fragments become avid targets for phagocytes called an ‘Eat me’ signal as Phosphatidylserine , which is normally present on the inner side of the cell, is expressed outside in Apoptotic bodies which are then recognised by macrophages, which engulfs these . The dead cell and its fragments are rapidly cleared before cellular contents have leaked out, so apoptotic cell death does not elicit an inflammatory reaction in the host. Apoptosis doesn’t cause inflammation; necrosis does . Caspases mediate both intrinsic and extrinsic apoptotic pathways .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Chromatin is lysed by endonucleases to form nucleosomes. True Option: C. Macrophages phagocytose remaining apoptotic bodies. True Option: D. Caspases are increased and mediate apoptosis. True</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is an anti-apoptotic gene?", "options": [{"label": "A", "text": "C-MYC", "correct": false}, {"label": "B", "text": "P 53", "correct": false}, {"label": "C", "text": "Bcl-2", "correct": true}, {"label": "D", "text": "BAX", "correct": false}], "correct_answer": "C. Bcl-2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bcl-2 Intrinsic (mitochondrial) pathway Apop totic sensors like BIM, BID, BAD, NOXA, and PUMA sense the presence of injury in a cell and regulate the balance between pro and anti-apoptotic factors . Then it will stimulate the pro-apoptotic factors like BAK, BAX, and P53 which induce apoptosis further by releasing CYTOCHROME-C into the cytosol . Apoptotic sensors inhibit the anti-apoptotic factors like BCL 1,2,6 BCL-XL MCL-1 which inhibit apoptosis by inhibiting the release of CYTOCHROME-C into the cytosol . Cytochrome-C activates A PAF-1 and together stimulates Caspase 9 , which activates endonuclease and protein breakdown to form apoptotic bodies from the dying cell. These apoptotic bodies are engulfed by the macrophages without causing an inflammatory host reaction.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. C-MYC. MYC is a proto-oncogene . Option: B. P 53. Tumour suppressor and Pro-Apoptotic. Option: D. BAX. Pro-Apoptotic .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The ladder pattern of DNA electrophoresis in apoptosis is caused by the action of the following enzyme –", "options": [{"label": "A", "text": "RNAase", "correct": false}, {"label": "B", "text": "Transglutaminase", "correct": false}, {"label": "C", "text": "DNAse", "correct": false}, {"label": "D", "text": "Caspase", "correct": true}], "correct_answer": "D. Caspase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Caspase The step ladder pattern of DNA electrophoresis in apoptosis is caused by DNA endonuclease activated by Caspase. Endo-nuclease cleaves the DNA into a multimer of 200 base pairs which gives a step ladder pattern . The smearing pattern of DNA electrophoresis is seen in necrosis because of karyolysis . The given image shows gel electrophoresis where: A= Control B= Stepladder pattern due to Apoptosis C= smear pattern due to Necrosis</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern ' Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. IgA antibodies against tissue transglutaminase are used in the diagnosis of Celiac disease . Option: C. Enzyme for degradation of DNA . Option: D. Not a correct answer</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Annexin V is a marker of –", "options": [{"label": "A", "text": "Apoptosis", "correct": true}, {"label": "B", "text": "Necrosis", "correct": false}, {"label": "C", "text": "Atherosclerosis", "correct": false}, {"label": "D", "text": "Inflammation", "correct": false}], "correct_answer": "A. Apoptosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Apoptosis Annexin V is a marker of apoptosis . Apoptotic cells express phosphatidyl-serine and thrombospondin on the outer layer of the plasma membrane which is recognized by Annexin V .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Necrosis is a pathologic process that is the consequence of severe injury. Doesn’t have any markers . Option: C. Atherosclerosis. The Marker includes CRP. Option: D. Inflammation. Markers include CRP, ESR, etc</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In apoptosis, Apaf-1 is activated by the release of which of the following substances from the mitochondria?", "options": [{"label": "A", "text": "BCL-2", "correct": false}, {"label": "B", "text": "BAX", "correct": false}, {"label": "C", "text": "BCL-XL", "correct": false}, {"label": "D", "text": "Cytochrome C", "correct": true}], "correct_answer": "D. Cytochrome C", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cytochrome C Intrinsic (mitochondrial) pathway Apoptotic sensors like BIM, BID, BAD, NOXA, and PUMA sense the presence of injury in a cell and regulate the balance between pro and anti-apoptotic factors . Then it will stimulate the pro-apoptotic factors like BAK, BAX, and P53 which induce apoptosis further by releasing CYTOCHROME-C into the cytosol . Apoptotic sensors inhibit the anti-apoptotic factors like BCL 1,2,6 BCL-XL MCL-1 which inhibit apoptosis by inhibiting the release of CYTOCHROME-C into the cytosol . Cytochrome-C activates APAF-1 and together stimulates Caspase 9 , which activates endonuclease and protein breakdown to form apoptotic bodies from the dying cell. These apoptotic bodies are engulfed by the macrophages without causing an inflammatory host reaction.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. BCL-2. Anti-apoptotic factors . Option: B. Pro-apoptotic factors Option: C. BCL-XL. Anti-apoptotic factors .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are features of apoptosis except:", "options": [{"label": "A", "text": "Cell shrinkage", "correct": false}, {"label": "B", "text": "Fragmentation of the nucleus", "correct": false}, {"label": "C", "text": "Intact plasma membrane", "correct": false}, {"label": "D", "text": "Enzymatic digestion of cellular contents", "correct": true}], "correct_answer": "D. Enzymatic digestion of cellular contents", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Enzymatic digestion of cellular contents Enzymatic digestion of cellular contents occurs in necrosis.</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern ' Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cell shrinkage. Seen in Apoptosis . Option: B. Fragmentation of nucleus. Seen in Apoptosis . Option: C. Intact plasma membrane. Seen in Apoptosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding apoptosis?", "options": [{"label": "A", "text": "Always Physiological", "correct": false}, {"label": "B", "text": "Always pathological", "correct": false}, {"label": "C", "text": "Can be physiological or pathological", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Can be physiological or pathological", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Can be physiological or pathological Apoptosis can be physiological or pathological but necrosis is always pathological .</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Always Physiological. Apoptosis is often physiological but it is not always. Option: B. Always pathological. Apoptosis is not always pathological. Option: D. None. Incorrect option.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are true regarding apoptotic bodies, except ?", "options": [{"label": "A", "text": "It is followed by the formation of cytoplasmic blebs", "correct": false}, {"label": "B", "text": "Can be seen in necrosis", "correct": true}, {"label": "C", "text": "Bounded by a plasma membrane", "correct": false}, {"label": "D", "text": "It can have nuclear material or not", "correct": false}], "correct_answer": "B. Can be seen in necrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Can be seen in necrosis The apoptotic cell first shows extensive surface membrane blebbing , which is followed by fragmentation of the dead cells into membrane-bound apoptotic bodies composed of cytoplasm and tightly packed organelles, with or without nuclear fragments .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is followed by the formation of cytoplasmic blebs. True . Option: C. Bounded by the plasma membrane. True . Option: D. It can have nuclear material or not. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the physiological cause of apoptosis?", "options": [{"label": "A", "text": "Removal of Epithelial cells in intestinal crypts", "correct": false}, {"label": "B", "text": "Regression of tissue post hormone withdrawal", "correct": false}, {"label": "C", "text": "During embryogenesis", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Apoptosis can be physiological or pathological but necrosis is always pathological .</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Elimination of potentially harmful self-reactive lymphocytes. Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Removal of Epithelial cells in intestinal crypts. True . Option: B. Regression of tissue post-hormone withdrawal. True . Option: C. During embryogenesis. True. Option: D. All of the above. True.</p>\n<p><strong>Extraedge:</strong></p><p>The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidyl serine on the outside , which are recognised and engulfed by macrophages</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Apoptotic Bodies are", "options": [{"label": "A", "text": "Cell membrane-bound with organelle and no nuclear fragments", "correct": false}, {"label": "B", "text": "Cell membrane-bound with organelle only", "correct": false}, {"label": "C", "text": "Cell membrane-bound with organelle with or without Nuclear fragments", "correct": true}, {"label": "D", "text": "Clumped chromatin bodies", "correct": false}], "correct_answer": "C. Cell membrane-bound with organelle with or without Nuclear fragments", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cell membrane-bound with organelle with or without Nuclear fragments Apoptosis is a pathway of programmed cell death in which cells activate enzymes that degrade the cells’ own nuclear DNA and nuclear and cytoplasmic proteins . The plasma membrane of the apoptotic cell remains intact , but the membrane is altered in such a way that the cell and its fragments become avid targets for phagocytes called an ‘Eat me’ signal as Phosphatidyl serine , which is normally present on the inner side of the cell, is expressed outside in Apoptotic bodies which are then recognised by macrophages, which engulfs these . The apoptotic cell first shows extensive surface membrane blebbing , which is followed by fragmentation of the dead cells into membrane-bound apoptotic bodies composed of cytoplasm and tightly packed organelles, with or without nuclear fragments . Apoptosis doesn’t cause inflammation; necrosis does . Caspases mediate both intrinsic and extrinsic apoptotic pathways .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cell membrane-bound with organelle and no nuclear fragments. False Option: B. Cell membrane-bound with organelle only. False Option: D. Clumped chromatin bodies. Chromatin condensation is the most characteristic feature of apoptosis .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are ‘BH-3 only proteins’ except:", "options": [{"label": "A", "text": "BIM", "correct": false}, {"label": "B", "text": "BID", "correct": false}, {"label": "C", "text": "BAD", "correct": false}, {"label": "D", "text": "MCL-1/SMAC", "correct": true}], "correct_answer": "D. MCL-1/SMAC", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MCL-1/SMAC Sensors : Members of this group, including BAD, BIM, BID, PUMA, and NOXA , contain only one BH domain, the third of the four BH domains, and hence are sometimes called BH3-only proteins . BH3-only proteins act as sensors of cellular stress and damage and regulate the balance between the other two groups, thus acting as arbiters of apoptosis.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. BIM. Apoptotic sensor . Option: C. BID. Apoptotic sensor . Option: D. BAD. Apoptotic sensor .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following induce pathological apoptosis except:", "options": [{"label": "A", "text": "Accumulation of misfolded proteins", "correct": false}, {"label": "B", "text": "Damaged DNA by anticancer drugs", "correct": false}, {"label": "C", "text": "Neutrophils after inflammatory response", "correct": true}, {"label": "D", "text": "Councilman bodies in viral hepatitis", "correct": false}], "correct_answer": "C. Neutrophils after inflammatory response", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neutrophils after inflammatory response Neutrophils after inflammatory reactions die by physiological apoptosis The following are the causes of pathological apoptosis- DNA damage by Radiation and cytotoxic anticancer drugs beyond repair. Accumulation of misfolded proteins . Apoptosis can be induced during certain infections , particularly viral infections eg: viral hepatitis . Apoptosis may also contribute to pathologic atrophy in parenchymal organs after duct obstruction , such as occurs in the pancreas, parotid gland, and kidney.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptotic hepatocytes were first clearly described in yellow fever by William Thomas Councilman and therefore have often been referred to as Councilman bodies ; while apoptosis occurs in many forms of liver disease, by convention this eponym is restricted to that disease. In the more frequent settings in which apoptotic hepatocytes are seen (e.g.: acute and chronic hepatitis) , the term acidophil bodies are used, due to their deeply eosinophilic staining characteristics . Foci of lobular hepatitis in chronic hepatitis C show an apoptotic hepatocyte (\"acidophil body\"; arrow) and a focus of mononuclear infiltration surrounding a more darkly stained, injured hepatocyte (double arrows).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Accumulation of misfolded proteins. Induces pathological apoptosis . Option: B. Damaged DNA by anticancer drugs. Induces pathological apoptosis . Option: D. Councilman bodies in viral hepatitis. Induces pathological apoptosis.</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is true regarding the mechanism of apoptosis by intrinsic pathway except?", "options": [{"label": "A", "text": "Damage is sensed by apoptotic sensors", "correct": false}, {"label": "B", "text": "Decrease in pro-apoptotic factors", "correct": true}, {"label": "C", "text": "Leaking of cyt c1 and APAF-1", "correct": false}, {"label": "D", "text": "Activate Caspase", "correct": false}], "correct_answer": "B. Decrease in pro-apoptotic factors", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Decrease in pro-apoptotic factors Intrinsic (mitochondrial) pathway: Apoptotic sensors like BIM, BID, BAD, NOXA, and PUMA sense the presence of injury in a cell and regulate the balance between pro and anti-apoptotic factors . Then it will stimulate the pro-apoptotic factors like BAK, BAX, and P53 which induce apoptosis further by releasing CYTOCHROME-C into the cytosol . Apoptotic sensors inhibit the anti-apoptotic factors like BCL 1,2,6 BCL-XL MCL-1 which inhibit apoptosis by inhibiting the release of CYTOCHROME-C into the cytosol . Cytochrome-C activates APAF-1 and together stimulates Caspase 9 , which activates endonuclease and protein breakdown to form apoptotic bodies from the dying cell. These apoptotic bodies are engulfed by the macrophages without causing an inflammatory host reaction.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Damage is sensed by apoptotic sensors. True . Option: C. Leaking of cyt c1 and APAF-1. True . Option: D. Activate Caspase. True .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are apoptotic sensors except?", "options": [{"label": "A", "text": "BIM", "correct": false}, {"label": "B", "text": "BID", "correct": false}, {"label": "C", "text": "BAD", "correct": false}, {"label": "D", "text": "BAK", "correct": true}], "correct_answer": "D. BAK", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>BAK BAK is a pro-apoptotic factor . BIM, BID, and BAD are all Apoptotic sensors along with NOXA, and PUMA .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. BIM. Apoptotic sensor . Option: C. BID. Apoptotic sensor . Option: D. BAD. Apoptotic sensor .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a pro-apoptotic factor?", "options": [{"label": "A", "text": "BAD", "correct": false}, {"label": "B", "text": "BAX", "correct": false}, {"label": "C", "text": "BAK", "correct": false}, {"label": "D", "text": "B and C", "correct": true}], "correct_answer": "D. B and C", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B and C BAX and BAK are both Pro Apoptotic factors . They contain the first three BH domains (BH1-3). On activation, BAX and/or BAK oligomerize within the outer mitochondrial membrane and enhance its permeability . The precise mechanism is not known. According to one model, they form a channel in the outer mitochondrial membrane that allows cytochrome c leakage from the intermembranous space .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. BAD. Apoptotic sensor . Option: B. BAX. Pro Apoptotic factors . Option: C. BAD. Pro Apoptotic factors .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is an anti-apoptotic factor?", "options": [{"label": "A", "text": "BCL-2", "correct": false}, {"label": "B", "text": "BCL- XL", "correct": false}, {"label": "C", "text": "MCL-1", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Intrinsic (mitochondrial) pathways: Apoptotic sensors like BIM, BID, BAD, NOXA, and PUMA sense the presence of injury in a cell and regulate the balance between pro and anti-apoptotic factors . Then it will stimulate the pro-apoptotic factors like BAK, BAX, and P53 which induce apoptosis further by releasing CYTOCHROME-C into the cytosol . Apoptotic sensors inhibit the anti-apoptotic factors like BCL 1,2,6 BCL-XL MCL-1 which inhibit apoptosis by inhibiting the release of CYTOCHROME-C into the cytosol . Cytochrome-C activates APAF-1 and together stimulates Caspase 9 , which activates endonuclease and protein breakdown to form apoptotic bodies from the dying cell. These apoptotic bodies are engulfed by the macrophages without causing an inflammatory host reaction.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. BCL-2. Anti-apoptotic factor . Option: C. BCL- XL. Anti-apoptotic factor . Option: D. MCL-1. Anti-apoptotic factor .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding Caspase?", "options": [{"label": "A", "text": "It has cytosine in its active site and cleaves after asparagine", "correct": false}, {"label": "B", "text": "It has cysteine in its active site and cleaves after asparagine", "correct": false}, {"label": "C", "text": "It has cytosine in its active site and cleaves after aspartate", "correct": false}, {"label": "D", "text": "It has cysteine in its active site and cleaves after aspartate", "correct": true}], "correct_answer": "D. It has cysteine in its active site and cleaves after aspartate", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It has cysteine in its active site and cleaves at aspartate Caspases are proteases containing cysteine in their active site and cleave proteins after aspartic residues . Like many proteases, caspases exist as inactive proenzymes and must undergo enzymatic cleavage to become active. The presence of active caspases is therefore a marker for cells undergoing apoptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It has cytosine in its active site and cleaves after asparagine. False . Option: B. It has cysteine in its active site and cleaves after asparagine. False . Option: C. It has cytosine in its active site and cleaves after aspartate. False .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which cells destroy the apoptotic bodies?", "options": [{"label": "A", "text": "Neutrophils", "correct": false}, {"label": "B", "text": "Macrophage", "correct": true}, {"label": "C", "text": "B lymphocytes", "correct": false}, {"label": "D", "text": "Cytotoxic T cells", "correct": false}], "correct_answer": "B. Macrophage", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Macrophage Removal of apoptotic bodies formed is done by macrophages through phagocytosis.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . Neutrophils are not involved in the phagocytosis of apoptotic bodies. Options: C, D . Lymphocytes are not involved in apoptosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is true?", "options": [{"label": "A", "text": "In normal cells, phosphatidyl serine is present on the outer layer of the plasma membrane", "correct": false}, {"label": "B", "text": "In apoptotic cells, it is present on the inner layer of the plasma membrane", "correct": false}, {"label": "C", "text": "During apoptosis, phosphatidyl serine flips out which is recognized by macrophage", "correct": true}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "C. During apoptosis, phosphatidyl serine flips out which is recognized by macrophage", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>During apoptosis, phosphatidyl serine flips out which is recognized by macrophage In healthy cells, phosphatidylserine is present on the inner leaflet of the plasma membrane, but in apoptotic cells , this phospholipid ‘flips’ out and is expressed on the outer layer of the membrane , where it is recognized by several macrophage receptors as it serves as ‘Eat me’ signal . Cells that are dying by apoptosis also secrete soluble factors that recruit phagocytes, and macrophages themselves may produce proteins that bind to apoptotic cells (but not live cells), leading to their engulfment. Apoptotic bodies may also become coated with natural antibodies and proteins of the complement system, notably C1q , which are recognized by phagocytes.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. In normal cells, phosphatidyl serine is present on the outer layer of the plasma membrane. Normally it is present on the inner layer . Option: B . In apoptotic cells, it is present on the inner layer of the plasma membrane. In apoptotic cells, it is present on the outer layer . Option: D . All are true. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is efferocytosis?", "options": [{"label": "A", "text": "Formation of the apoptotic body from cell", "correct": false}, {"label": "B", "text": "Process of flipping out of phosphatidyl serine", "correct": false}, {"label": "C", "text": "Process of engulfing of the apoptotic body by macrophage", "correct": true}, {"label": "D", "text": "Leakage of mediators of apoptosis", "correct": false}], "correct_answer": "C. Process of engulfing of the apoptotic body by macrophage", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Process of engulfing of the apoptotic body by macrophage The process of apoptotic cell phagocytosis is called efferocytosis ; it is so efficient that dead cells disappear, often within minutes, without leaving a trace. In addition, the production of pro-inflammatory cytokines is reduced in macrophages that have ingested apoptotic cells.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Formation of the apoptotic body from the cell. Incorrect . Option: B. Process of flipping out of phosphatidyl serine. Incorrect . Option: D. Leakage of mediators of apoptosis. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are regulators of apoptosis?", "options": [{"label": "A", "text": "NOXA", "correct": false}, {"label": "B", "text": "Smac/ DIABLO", "correct": true}, {"label": "C", "text": "PUMA", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. Smac/ DIABLO", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Smac/ DIABLO In the mitochondrial pathway, active caspase-9 then triggers a cascade of caspase activation by cleaving and thereby activating other pro-caspases (such as caspase-3), which mediate the execution phase of apoptosis. Other mitochondrial proteins with arcane names like Smac/DIABLO enter the cytoplasm, where they bind to and neutralize cytoplasmic proteins that function as physiologic inhibitors of apoptosis (IAPs) . The normal function of the IAPs is to block the inappropriate activation of caspases , including executioners like caspase-3, and keep cells alive. Thus, IAP inhibition permits the initiation of the caspase cascade.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. NOXA. Apoptosis sensors . Option: C. PUMA. Apoptosis sensors . Option: D. All of the above. Incorrect . NOTE: Such questions in the paper can be solved by the elimination of other options, if one knows that PUMA and NOXA are Apoptosis sensors , it will rule out options A, C and D .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is FAS protein?", "options": [{"label": "A", "text": "CD 99", "correct": false}, {"label": "B", "text": "CD 98", "correct": false}, {"label": "C", "text": "CD 95", "correct": true}, {"label": "D", "text": "CD 91", "correct": false}], "correct_answer": "C. CD 95", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD 95 The extrinsic pathway is initiated by the engagement of plasma membrane death receptors . Death receptors are members of the tumour necrosis factor ( TNF ) receptor family that contains a cytoplasmic domain involved in protein-protein interactions. This death domain is essential for delivering apoptotic signals. The best-known death receptors are the type 1 TNF receptor (TNFR1) and a related protein called Fas (CD95)</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CD 99. Incorrect . Option: B. CD 98. Incorrect . Option: D. CD 91. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the death domain?", "options": [{"label": "A", "text": "TNFR1", "correct": false}, {"label": "B", "text": "CD95", "correct": false}, {"label": "C", "text": "Fas- Fas ligand", "correct": true}, {"label": "D", "text": "Procaspase - 8", "correct": false}], "correct_answer": "C. Fas- Fas ligand", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fas- Fas ligand Extrinsic pathway: The mechanism of apoptosis induced by Fas, a death receptor expressed on many cell types. The ligand for Fas is called Fas ligand (FasL) . FasL is expressed on T cells that recognize self-antigens (and functions to eliminate self-reactive lymphocytes that also express the receptor Fas upon recognition of self-antigens) and on some CTLs that kill virus-infected and tumour cells. When FasL binds to Fas , three or more molecules of Fas are brought together, and their cytoplasmic death domains form a binding site for an adaptor protein called FADD (Fas-associated death domain) .</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. TNFR1. Incorrect . Option: B. CD95. Incorrect . Option: D. Procaspase - 8. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is false regarding the extrinsic pathway of apoptosis?", "options": [{"label": "A", "text": "Fas- FasL formation", "correct": false}, {"label": "B", "text": "Main death receptor is the type 1 TNF receptor", "correct": false}, {"label": "C", "text": "Associated with FADD", "correct": false}, {"label": "D", "text": "Induced by FLIP protein", "correct": true}], "correct_answer": "D. Induced by FLIP protein", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Induced by FLIP protein This extrinsic apoptosis pathway can be inhibited by a protein called FLIP , which binds to pro caspase-8 , thereby blocking FADD binding , but cannot activate the caspase. Some viruses and normal cells produce FLIP as a mechanism to protect themselves from Fas-mediated apoptosis.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. TNFR1. Incorrect . Option: B. CD95. Incorrect . Option: D. Procaspase - 8. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>CAUSES OF APOPTOSIS PHYSIOLOGICAL During embryogenesis- Cells during organogenesis Hormonal withdrawal - Endometrial cell breakdown during menstrual cycle, menopause. Removal of self reactive lymphocytes- In thymus (Central tolerance) Post inflammatory response- Excess inflammatory cells are remove PATHOLOGICAL DNA Damaged by Radiotherapy, Chemotherapy, Hypoxia Accumulation of misfolded protein cell death in viral infection. Eg: HIV, Hepatitis virus. In organ due to ductal obstruction Eg: Parotid gland Pancreas</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the initiator caspase for the intrinsic pathway?", "options": [{"label": "A", "text": "Caspase 8", "correct": false}, {"label": "B", "text": "Caspase 9", "correct": true}, {"label": "C", "text": "Caspase 1", "correct": false}, {"label": "D", "text": "Caspase 7", "correct": false}], "correct_answer": "B. Caspase 9", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Caspase 9 The initiator caspase for the intrinsic pathway of apoptosis is caspase 9.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Initiator caspase for extrinsic pathway Option s : C, D. not involved in apoptosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is exclusive to the extrinsic pathway of apoptosis?", "options": [{"label": "A", "text": "Caspase 8", "correct": true}, {"label": "B", "text": "Caspase 9", "correct": false}, {"label": "C", "text": "Caspase 3", "correct": false}, {"label": "D", "text": "Caspase 6", "correct": false}], "correct_answer": "A. Caspase 8", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Caspase 8 Caspase 8 is the initiator of caspase for the extrinsic pathway . MNEMONIC: Caspase E ight is the initiator for the E xtrinsic pathway.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Caspase 9. Initiator caspase for the intrinsic pathway . Option: C. Caspase 3. Executioner caspase which is common for extrinsic and intrinsic pathways of apoptosis. Option: D. Caspase 6. Executioner caspase which is common for extrinsic and intrinsic pathways of apoptosis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following are used to diagnose apoptosis-", "options": [{"label": "A", "text": "Stain annexing V", "correct": false}, {"label": "B", "text": "Estimation of cytochrome c", "correct": false}, {"label": "C", "text": "TUNEL", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Apoptosis can be measured by: Estimation of cytochrome c Estimation of caspases Stain by Annexin V DNA agar gel electrophoresis TUNEL (Terminal UTP nick end labelling)</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidylserine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Stain annexing V. Correct . Option: B. Estimation of cytochrome c. Correct . Option: C. TUNEL Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Label the following pattern of DNA agar gel electrophoresis seen in the image given below:", "options": [{"label": "A", "text": "Apoptosis, Normal cell, Necrosis", "correct": false}, {"label": "B", "text": "Normal cell, Necrosis, Apoptosis", "correct": false}, {"label": "C", "text": "Necrosis, Apoptosis, Normal cell", "correct": false}, {"label": "D", "text": "Normal cell, Apoptosis, Necrosis", "correct": true}], "correct_answer": "D. Normal cell, Apoptosis, Necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812522214-QTDP008028IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Normal cell, Apoptosis, Necrosis Endo-nuclease cleaves the DNA into a multimer of 200 base pairs which gives a step ladder pattern in apoptosis . The smearing pattern of DNA electrophoresis is seen in necrosis because of karyolysis . The given image shows gel electrophoresis where: A= Control/ Normal cell B= Stepladder pattern due to Apoptosis C= smear pattern due to Necrosis</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Apoptosis, Normal cell, Necrosis. Incorrect . Option: B. Normal cell, Necrosis, Apoptosis. Incorrect . Option: C. Necrosis, Apoptosis, Normal cell. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "FLIP protein _______ the _________pathway of apoptosis:", "options": [{"label": "A", "text": "Stimulates, extrinsic", "correct": false}, {"label": "B", "text": "Stimulates, intrinsic", "correct": false}, {"label": "C", "text": "Inhibits, extrinsic", "correct": true}, {"label": "D", "text": "Inhibits, intrinsic", "correct": false}], "correct_answer": "C. Inhibits, extrinsic", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Inhibits, extrinsic FLIP protein inhibits the extrinsic pathway of apoptosis, which is mediated by the death receptor. Mechanism of apoptosis: There are two distinct pathways which can lead to caspase activation and cause apoptosis of the cell. The mitochondrial or intrinsic pathway The death receptor or extrinsic pathway This extrinsic apoptosis pathway can be inhibited by a protein called FLIP , which binds to pro caspase-8 , thereby blocking FADD binding , but cannot activate the caspase. Some viruses and normal cells produce FLIP as a mechanism to protect themselves from Fas-mediated apoptosis.</p>\n<p><strong>Highyeild:</strong></p><p>Apoptosis The extrinsic pathway is mediated by FAS (TNF receptor)-FAS Ligand (TNF) via Caspase 8 . The intrinsic/ Mitochondrial pathway is mediated by the Apoptosome which activates Caspase 9 Both intrinsic and extrinsic pathways then activate Caspase 3 and 6 , which cause the endonuclease activation and protein breakdown leading to the formation of Apoptotic bodies which contain Phosphatidyl serine on the outside , which are recognised and engulfed by macrophages</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Stimulates, extrinsic. Incorrect . Option: B. Stimulates, intrinsic. Incorrect . Option: D. Inhibits, intrinsic. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 39 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 2-year-old child presents with the complaint of recurrent cough and breathing difficulty usually at night or early morning. On examination, the baby is slightly dyspneic with prolonged expiration and wheezes heard. Which of the following devices will be used most commonly by this child?", "options": [{"label": "A", "text": "A", "correct": false}, {"label": "B", "text": "B", "correct": false}, {"label": "C", "text": "C", "correct": true}, {"label": "D", "text": "D", "correct": false}], "correct_answer": "C. C", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1725359126115-photos-1725270863057-QTDK056001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C The above case scenario is of an asthma patient. The age of the child is 2 years so the device most commonly used is MDI with a spacer with a facemask.</p>\n<p><strong>Highyeild:</strong></p><p>Metered Dose Inhaler (MDI) ROTAHALER Metered Dose Inhaler (MDI) with spacer with facemask Metered Dose Inhaler (MDI) with spacer Children <4-year-old: MDI with spacer with face mask Children >4-year-old: MDI with spacer preferred Children >12-year-old: MDI used directly. Use of spacer improves drug deposition.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 10-year-old girl presents with the complaint of recurrent cough, wheezing, and breathing difficulty usually at night or early morning. These symptoms are usually present daily. On examination, she is dyspneic, anxious, and has a prolonged expiration. Due to these symptoms, she is missing school which affects her studies. How will you manage the patient?", "options": [{"label": "A", "text": "Short-acting β-agonist (SABA) whenever symptoms", "correct": false}, {"label": "B", "text": "Low-dose inhaled steroids + SABA (Short-acting β-agonist)", "correct": false}, {"label": "C", "text": "Low-dose inhaled steroids + LABA (Long-acting β-agonist)", "correct": true}, {"label": "D", "text": "Low-dose inhaled steroids + Short-acting β-agonist (SABA) whenever required", "correct": false}], "correct_answer": "C. Low-dose inhaled steroids + LABA (Long-acting β-agonist)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Low-dose inhaled steroids + LABA (Long-acting β-agonist) The above case scenario is of moderate persistent asthma patients. The child is anxious with increased respiratory rate, chest indrawing, and symptoms affecting her studies. So the management will include low dose Inhaled Corticosteroids ICS + LABALong -acting β-agonist or medium-dose ICS Inhaled Corticosteroids. STEPWISE TREATMENT OF ASTHMA: Symptoms Treatment Step 4: Severe persistent Continuous Limited physical activity High dose inhaled steroids+ Long-acting β 2 agonist Add montelukast Refer to special Step 3: Moderate persistent Daily use β 2 , agonist Daily attack affects activity Low dose inhaled steroids + Long-acting β 2 agonist OR Medium dose inhaled steroids Step 2: Mild persistent Low grade symptoms twice a month Nighttime awakening once per month Low dose inhaled steroids Short-acting β 2 , agonist, whenever symptoms Step 1: Intermittent Infrequent Asymptomatic and normal PEFR between attack Short-acting β 2 agonist, whenever symptoms</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 7-year-old child came with a recurrent cough and breathing difficulty usually at night or early morning. Her mother also had a history of asthma. Which of the following are diagnostic markers of asthma in children?", "options": [{"label": "A", "text": "Forced Expiratory Volume FEV1/ Forced Vital Capacity FVC less than 60%", "correct": false}, {"label": "B", "text": "Improve in Forced Expiratory Volume FEV1 > 12% after SABA Short-acting β-agonist", "correct": true}, {"label": "C", "text": "Diurnal Peak Expiratory Flow Rate PEFR variation more than or equal to 15%", "correct": false}, {"label": "D", "text": "Decrease in FEV1 by >20% during or after exercise", "correct": false}], "correct_answer": "B. Improve in Forced Expiratory Volume FEV1 > 12% after SABA Short-acting β-agonist", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Improve in Forced Expiratory Volume FEV1 > 12% after SABA Short-acting β-agonist Diagnostic markers of asthma in children are:- Forced Expiratory VolumeFEV1/Forced Vital Capacity FVC < 80% OR 0.8 Improvement in FEV1 >12% after Short-acting β-agonist SABA Diurnal Peak Expiratory Flow Rate PEFR variation >20% Decrease in FEV1 by 15% during or after exercises Exhaled nitric oxide >20ppb supports clinical diagnosis of asthma Low FEF 27 (a best marker of airway obstruction)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An 8-year-old child came with a history of asthma. Currently, his symptom has increased as he complains of recurrent cough, wheezing, and breathing difficulty early in the morning. His symptoms are coming daily despite daily use of Short-acting β-agonist SABA. In which category will you categorize the patient?", "options": [{"label": "A", "text": "Mild persistent", "correct": false}, {"label": "B", "text": "Moderate persistent", "correct": true}, {"label": "C", "text": "Severe persistent", "correct": false}, {"label": "D", "text": "Intermittent persistent", "correct": false}], "correct_answer": "B. Moderate persistent", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Moderate persistent The above case scenario is of moderate persistent asthma. STEPWISE TREATMENT OF ASTHMA: Symptoms Treatment Step 4: Severe persistent Continuous Limited physical activity High dose inhaled steroids+ Long-acting β 2 agonist Add montelukast Refer to special Step 3: Moderate persistent Daily use β 2 , agonist Daily attack affects activity Low dose inhaled steroids + Long-acting β 2 agonist OR Medium dose inhaled steroids Step 2: Mild persistent Low grade symptoms twice a month Nighttime awakening once per month Low dose inhaled steroids Short-acting β 2 , agonist, whenever symptoms Step 1: Intermittent Infrequent Asymptomatic and normal PEFR between attack Short-acting β 2 agonist, whenever symptoms GRADING OF SEVERITY OF ASTHMA Clinical parameter Mild Moderate Bovoro Color Normal Normal Pale Sensorium Normal Anxious Agitated Respiratory rate Increased Increased Increased Dyspnea Absent Moderate Severe Speech Can speak sentancos Can speak in phrases Difficulty in speech Use of accessory muscles Nil or minimal Chost Indrawing Indrawing; nasal flare Pulsus paradoxus 10 mm 10-20 mm >20 mm Rhonchi Expiratory and/or Inspiratory Expiratory and/or Inspiratory Expiratory or absent Peak expiratory flow rate >80% 60-80% <80% Oxygen saturation >95% 00-05% <90%</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In the above patient, what will be the recommended management?", "options": [{"label": "A", "text": "Short-acting β-agonist (SABA) + low dose ICS Inhaled Corticosteroids", "correct": false}, {"label": "B", "text": "Short-acting β-agonist SABA + medium dose ICS Inhaled Corticosteroids", "correct": true}, {"label": "C", "text": "Short-acting β-agonist SABA+ high dose ICS Inhaled Corticosteroids", "correct": false}, {"label": "D", "text": "Short-acting β-agonist (SABA) + high dose Inhaled Corticosteroids (ICS) Long-acting β-agonist (LABA)", "correct": false}], "correct_answer": "B. Short-acting β-agonist SABA + medium dose ICS Inhaled Corticosteroids", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Short-acting β-agonist SABA + medium dose ICS Inhaled Corticosteroids The above case scenario is of moderate persistent asthma. The management will include- Short-acting β-agonist SABA + medium dose ICS Inhaled Corticosteroids or low dose ICS Inhaled Corticosteroids + LABA Long-acting β-agonist. STEPWISE TREATMENT OF ASTHMA:- Symptoms Treatment Step 4: Severe persistent Continuous Limited physical activity High dose inhaled steroids+ Long-acting β 2 agonist Add montelukast Refer to special Step 3: Moderate persistent Daily use β 2 , agonist Daily attack affects activity Low dose inhaled steroids + Long-acting β 2 agonist OR Medium dose inhaled steroids Step 2: Mild persistent Low grade symptoms twice a month Nighttime awakening once per month Low dose inhaled steroids Short-acting β 2 , agonist, whenever symptoms Step 1: Intermittent Infrequent Asymptomatic and normal PEFR between attack Short-acting β 2 agonist, whenever symptoms</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 9-year-old came with complaining of recurrent cough, wheezing, and breathing difficulty usually twice a month though he is able to do his daily activities normally. His mother also had a history of asthma. What will be the recommended management of this patient?", "options": [{"label": "A", "text": "Short-acting β-agonist SABA as needed", "correct": false}, {"label": "B", "text": "Short-acting β-agonist SABA as needed + low dose ICS-Inhaled Corticosteroids", "correct": true}, {"label": "C", "text": "Short-acting β-agonist SABA daily + low dose ICS- Inhaled Corticosteroids", "correct": false}, {"label": "D", "text": "Short-acting β-agonist SABA as needed + medium dose ICS-Inhaled Corticosteroids", "correct": false}], "correct_answer": "B. Short-acting β-agonist SABA as needed + low dose ICS-Inhaled Corticosteroids", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Short-acting β-agonist SABA as needed + low dose ICS-Inhaled Corticosteroids The above case scenario is of mild persistent asthma. The management will include SABA as needed + low dose ICS. STEPWISE TREATMENT OF ASTHMA: Symptoms Treatment Step 4: Severe persistent Continuous Limited physical activity High dose inhaled steroids+ Long-acting β 2 agonist Add montelukast Refer to special Step 3: Moderate persistent Daily use β 2 , agonist Daily attack affects activity Low dose inhaled steroids + Long-acting β 2 agonist OR Medium dose inhaled steroids Step 2: Mild persistent Low grade symptoms twice a month Nighttime awakening once per month Low dose inhaled steroids Short-acting β 2 , agonist, whenever symptoms Step 1: Intermittent Infrequent Asymptomatic and normal PEFR between attack Short-acting β 2 agonist, whenever symptoms</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The above patient’s symptoms will be categorized as?", "options": [{"label": "A", "text": "Intermittent symptoms", "correct": false}, {"label": "B", "text": "Mild persistent symptoms", "correct": true}, {"label": "C", "text": "Moderate persistent symptoms", "correct": false}, {"label": "D", "text": "Severe persistent symptoms", "correct": false}], "correct_answer": "B. Mild persistent symptoms", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mild persistent symptoms The above case scenario is of mild persistent asthma. STEPWISE TREATMENT OF ASTHMA: Symptoms Treatment Step 4: Severe persistent Continuous Limited physical activity High dose inhaled steroids+ Long-acting β 2 agonist Add montelukast Refer to special Step 3: Moderate persistent Daily use β 2 , agonist Daily attack affects activity Low dose inhaled steroids + Long-acting β 2 agonist OR Medium dose inhaled steroids Step 2: Mild persistent Low grade symptoms twice a month Nighttime awakening once per month Low dose inhaled steroids Short-acting β 2 , agonist, whenever symptoms Step 1: Intermittent Infrequent Asymptomatic and normal PEFR between attack Short-acting β 2 agonist, whenever symptoms GRADING OF SEVERITY OF ASTHMA Clinical parameter Mild Moderate Bovoro Color Normal Normal Pale Sensorium Normal Anxious Agitated Respiratory rate Increased Increased Increased Dyspnea Absent Moderate Severe Speech Can speak sentancos Can speak in phrases Difficulty in speech Use of accessory muscles Nil or minimal Chost Indrawing Indrawing; nasal flare Pulsus paradoxus 10 mm 10-20 mm >20 mm Rhonchi Expiratory and/or Inspiratory Expiratory and/or Inspiratory Expiratory or absent Peak expiratory flow rate >80% 60-80% <80% Oxygen saturation >95% 00-05% <90%</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following conditions will be considered in a life-threatening asthma? Cyanosis Silent chest (Peak Expiratory Flow Rate) PEFR < 20% of predicted Altered sensorium Oxygen saturation < 85% Select the correct answer from given below code:-", "options": [{"label": "A", "text": "1, 2, and 4", "correct": false}, {"label": "B", "text": "1, 2, 3, and 4", "correct": false}, {"label": "C", "text": "1, 2, and 5", "correct": false}, {"label": "D", "text": "1, 2, 3, 4, and 5", "correct": true}], "correct_answer": "D. 1, 2, 3, 4, and 5", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>1, 2, 3, 4, and 5 When to consider life-threatening asthma: Cyanosis Silent chest Peak Expiratory Flow Rate (PEFR) <30% of predicted Altered sensorium Oxygen saturation <90%</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 14-year-old child came with the complaint of recurrent cough, wheezing, and breathing difficulty usually early in the morning. These symptoms occur almost daily despite using high doses (Inhaled Corticosteroid) of ICS. His mother also had a history of asthma. Which IgE antibody is used nowadays?", "options": [{"label": "A", "text": "OMALIZUMAB", "correct": true}, {"label": "B", "text": "MEPOLIZUMAB", "correct": false}, {"label": "C", "text": "DUPILUMAB", "correct": false}, {"label": "D", "text": "ADALIMUMAB", "correct": false}], "correct_answer": "A. OMALIZUMAB", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>OMALIZUMAB The IgE antibody used for asthma nowadays is It binds to IgE and blocks its action on the IgE receptor. Indicated in children > 6 years with severe asthma on the max dose of ICS/OCS</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 15-year-old child came with the complaint of recurrent cough, wheezing, and breathing difficulty usually early in the morning. These symptoms occur almost daily despite using high doses of Inhaled Corticosteroids ICS. His mother also had a history of asthma. Doctor advised him to give MEPOLIZUMAB. What is the mechanism of action of this drug?", "options": [{"label": "A", "text": "Anti-IgE antibody", "correct": false}, {"label": "B", "text": "Anti-IL-5 antibody", "correct": true}, {"label": "C", "text": "Anti-IL-4 antibody", "correct": false}, {"label": "D", "text": "Anti-IL-13 antibody", "correct": false}], "correct_answer": "B. Anti-IL-5 antibody", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anti-IL-5 antibody MEPOLIZUMAB is an anti IL-5 . It blocks IL-5-mediated eosinophilopoiesis. Indicated in children > 12 years with severe eosinophilic asthma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not included in the discharge criteria of the patient with asthma from the hospital?", "options": [{"label": "A", "text": "Patient should be on discharge medications for 12 hrs prior to discharge.", "correct": true}, {"label": "B", "text": "Correct inhaler technique is checked and recorded", "correct": false}, {"label": "C", "text": "If the recorded Peak Expiratory Flow Rate PEFR is >75% of predicted of the best and Peak Expiratory Flow Rate PEFR diurnal variation is < 20%, treatment should include soluble steroids and inhaled steroids in addition to the bronchodilation", "correct": false}, {"label": "D", "text": "Patients should be given a self-management plan or instructions should be given to the parents", "correct": false}], "correct_answer": "A. Patient should be on discharge medications for 12 hrs prior to discharge.", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Patient should be on discharge medications for 12 hrs prior to discharge. Discharge criteria from the hospital include: Patients should be on discharge medication for 24 hours prior to discharge. The correct inhaler technique is checked and recorded. If recorded PEFR >75% of predicted the best and PEFR diurnal variation is less than 20%, treatment should include soluble steroids tablets and inhaled steroids in addition to the bronchodilator. The patient should be given a self-management plan or instructions should be given to the parents.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 15-year-old child came to a paediatric emergency with the complaint of recurrent cough, wheezing, and breathing difficulty since morning. His symptoms are continuous for the past 1 week despite the use of SABA + high dose ICS + LABA. Currently, he is unconscious. What will be the management of this patient?", "options": [{"label": "A", "text": "Injection terbutaline s/c", "correct": false}, {"label": "B", "text": "Inhaled salbutamol", "correct": false}, {"label": "C", "text": "Injection hydrocortisone", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above The above case scenario is of life-threatening asthma. The presence of any of the following indicates life-threatening asthma. Cyanosis, silent chest, poor respiratory efforts, exhaustion or fatigue, altered sensorium, PEFR<30% of predicted, and oxygen saturation <90%. Such patients should immediately receive oxygen by mask or hood. An injection of terbutaline or adrenaline is given subcutaneously, inhalation of salbutamol or terbutaline and ipratropium is started, an injection of hydrocortisone (5 mg/kg) is given and arrangements are made to transfer the patient to an intensive care unit (ICU) preferably with an accompanying physician. If the patient shows improvement, the salbutamol/ terbutaline inhalation is continued every 20-30 minutes, and hydrocortisone (3-5 mg/kg) is continued every 6-8 hours till the patient starts accepting orally. If the patient does not improve or deteriorate a slow IV infusion of magnesium sulfate (SO mg/kg) or a loading dose of theophylline is given. If there is no improvement with this management, the patient is prepared for mechanical ventilation. Patients should also be screened for causes of poor response such as acidosis, pneumothorax, electrolyte imbalance and infection, and treated accordingly.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An infant presented with erythematous lesions on the cheek, and extensor aspect of limbs, mother has a history of bronchial asthma, and the probable diagnosis is:", "options": [{"label": "A", "text": "Airborne contact dermatitis", "correct": false}, {"label": "B", "text": "Atopic dermatitis", "correct": true}, {"label": "C", "text": "Seborrheic dermatitis", "correct": false}, {"label": "D", "text": "Infectious eczematoid dermatitis", "correct": false}], "correct_answer": "B. Atopic dermatitis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1682884939517-QTDK056013IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Atopic dermatitis Atopic dermatitis is associated with a history of bronchial asthma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 7-year-old child, known for severe persistent asthma, on Inhaled Corticosteroids ICS and salmeterol combination + montelukast arrives in an emergency in severe respiratory distress, cyanosis, and chest auscultation reveals silent chest. The child is not able to speak sentences. What is the first step of management in this child?", "options": [{"label": "A", "text": "Salbutamol by nebulisation", "correct": false}, {"label": "B", "text": "Subcutaneous adrenaline", "correct": false}, {"label": "C", "text": "Intubation", "correct": false}, {"label": "D", "text": "Oxygen by mask", "correct": true}], "correct_answer": "D. Oxygen by mask", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Oxygen by mask The first line of management of severe persistent asthma is oxygen by mask.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is most commonly preferred in the 5-year-old asthma patient?", "options": [{"label": "A", "text": "A", "correct": false}, {"label": "B", "text": "B", "correct": true}, {"label": "C", "text": "C", "correct": false}, {"label": "D", "text": "D", "correct": false}], "correct_answer": "B. B", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1725359186495-photos-1725270863418-QTDK056015IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B Children < 4-year-old: MDI Metered Dose Inhaler with spacer with face mask Children >4-year-old: MDI Metered Dose Inhaler with spacer preferred Children >12-year-old: MDI Metered Dose Inhaler used directly. The use of a spacer improves drug deposition. MDI Metered Dose Inhaler with spacer with facemask MDI Metered Dose Inhaler with spacer ROTAHALER MDI Metered Dose Inhaler</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is an indication of using mast cell stabilizers in childhood asthma?", "options": [{"label": "A", "text": "Aspirin-induced asthma", "correct": false}, {"label": "B", "text": "Severe asthma", "correct": false}, {"label": "C", "text": "Exercise-induced asthma", "correct": true}, {"label": "D", "text": "Status asthmaticus", "correct": false}], "correct_answer": "C. Exercise-induced asthma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Exercise-induced asthma Mast cell stabilizers (such as cromolyn sodium and nedocromil sodium) inhibit the degranulation of mast cells and be effective for preventing exercise-induced bronchospasm and as a treatment option in mild-moderate asthma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 26 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Identify the wrong match in relation to the type of atelectasis with its causative factor:", "options": [{"label": "A", "text": "Resorption - Bronchial asthma", "correct": false}, {"label": "B", "text": "Compression- Pneumothorax", "correct": false}, {"label": "C", "text": "Contraction- Pleural fibrosis", "correct": false}, {"label": "D", "text": "Compression- Bronchiectasis", "correct": true}], "correct_answer": "D. Compression- Bronchiectasis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Compression- Bronchiectasis Compression atelectasis occurs when an external force compresses the lung, such as in the case of a pneumothorax (air in the pleural cavity) or a hemothorax (blood in the pleural cavity). It is not caused by Bronchiectasis.</p>\n<p><strong>Highyeild:</strong></p><p>Type of Atelectasis Definition Causative Factors Resorption atelectasis Airway obstruction prevents air from reaching the alveoli, causing the absorption of alveolar air into the bloodstream and resulting in the collapse of the affected area of the lung. ● Bronchial asthma, ● Chronic bronchitis, ● Bronchiectasis, and ● Postoperative states. Compression atelectasis External compression of the lung, which prevents expansion of the lung during inspiration ● Pneumothorax, ● Hemothorax, ● Pleural effusion, ● Tumor Contraction atelectasis Fibrosis or scarring of the lung or pleura, which prevents expansion of the lung during inspiration ● Pleural fibrosis, ● Lung fibrosis, ● Tuberculosis, ● Sarcoidosis</p>\n<p><strong>Table:</strong></p><p>Type of Atelectasis Definition Causative Factors Resorption atelectasis Airway obstruction prevents air from reaching the\n alveoli, causing the absorption of alveolar air into the bloodstream\n and resulting in the collapse of the affected area of the lung. Bronchial asthma, Chronic bronchitis, Bronchiectasis, and Postoperative states. Compression atelectasis External compression of the lung, which prevents\n expansion of the lung during inspiration Pneumothorax, Hemothorax, Pleural effusion, Tumor Contraction atelectasis Fibrosis or scarring of the lung or pleura, which\n prevents expansion of the lung during inspiration Pleural fibrosis, Lung fibrosis, Tuberculosis, Sarcoidosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 1st-year medical student has learnt in his embryology classes that notochord, a rod-like structure develops between ectoderm and endoderm. He wonders whether it is present in adults as well. So, he comes to you to clarify his doubt. How will you explain to him the fate of notochord in the fetus?", "options": [{"label": "A", "text": "It develops into the vertebral column", "correct": false}, {"label": "B", "text": "It develops into the spinal cord", "correct": false}, {"label": "C", "text": "It undergoes atrophy", "correct": true}, {"label": "D", "text": "It remains persistent in adults as well", "correct": false}], "correct_answer": "C. It undergoes atrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It undergoes atrophy Notochord is a rod-like structure that lies between endoderm and ectoderm . It is essential for the development of the nervous system and primitive skeletal structures . However, it undergoes atrophy in the fetal life and this is known as physiologic atrophy . So, it is not seen in adults. Hence, the correct option is C.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It develops into the vertebral column. Incorrect because the nucleus pulposus of the notochord helps in the formation of intervertebral joints but the remaining notochord undergoes atrophy . Option: B. It develops into the spinal cord. Incorrect because the spinal cord is developed from the neural tube . A neural tube is formed in response to signaling from the notochord but the notochord itself does not develop into the spinal cord. Option: D. It remains persistent in adults as well. Incorrect because notochord is not present in adults . It undergoes atrophy in fetal life .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of these are examples of physiologic atrophy? Post-parturition decrease in size of the uterus Notochord Cachexia Senile atrophy Disuse atrophy Select the correct answer from the given below code:", "options": [{"label": "A", "text": "1,2,3,4,5", "correct": false}, {"label": "B", "text": "1,2", "correct": true}, {"label": "C", "text": "3,4,5", "correct": false}, {"label": "D", "text": "1,4,5", "correct": false}], "correct_answer": "B. 1,2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>1,2 A decrease in the size of the uterus after the delivery of the baby is an example of physiologic atrophy . Notochord undergoes atrophy during fetal development, which is an example of physiologic atrophy . Cachexia refers to marked muscle wasting in chronic inflammatory states and cancer . This is an example of pathologic atrophy . Senile atrophy refers to atrophy of the brain in the elderly due to ischemia resulting from atherosclerosis . This is an example of pathologic atrophy . Disuse atrophy is seen in the case of plaster casts when the bone is immobilised and unable to move. This is an example of pathologic atrophy . So, only 1 and 2 are examples of physiologic atrophy. Hence, the correct answer is B .</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from the decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Extraedge:</strong></p><p>Cancer cachexia syndrome is a syndrome in which the patient experiences weight loss due to poor appetite and looks fatigued . Cachexia occurs due to atrophy and the enzyme that plays a role in atrophy is ubiquitin ligase which helps in attaching ubiquitin to proteins so that they are available to be degraded by proteasome .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Identify the image and select the statement which correctly represents it:", "options": [{"label": "A", "text": "It is seen in young individuals", "correct": false}, {"label": "B", "text": "It occurs due to the disuse of organs", "correct": false}, {"label": "C", "text": "It occurs due to atherosclerosis", "correct": true}, {"label": "D", "text": "Sulci is narrowed while gyri are widened", "correct": false}], "correct_answer": "C. It occurs due to atherosclerosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812028763-QTDP005003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It occurs due to atherosclerosis A gradual decrease in blood supply (chronic ischemia) to a tissue as a result of slowly developing arterial occlusive disease results in tissue atrophy . In late adult life , the brain may undergo progressive atrophy, mainly because of reduced blood supply as a result of atherosclerosis . This is called senile atrophy . The given figure demonstrates wide sulci and narrow gyri , which is seen in senile atrophy. Hence, the correct option is C. Represents the normal brain of a young adult. Represents senile atrophy.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is seen in young individuals. Incorrect Option: B. It occurs due to the disuse of organs. Incorrect because senile atrophy occurs due to ischemia and not due to disuse . An example of disuse atrophy is plaster casts . Option: D. Sulci are narrowed while gyri are widened. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 75-year-old man was brought by his son to medicine OPD. He complains that his father does not remember routine events of his life, a few days earlier he was lost on his way while returning from the market. He speaks very slowly and in a low voice. On further investigations, it was found that he was able to do simple calculations but his MMSE (Mini-Mental State Examination) score was 21/30. On examination, blood pressure was 130/80, and heart rate 70/min. MRI was done. What changes are expected to be seen on MRI?", "options": [{"label": "A", "text": "Cerebral Atrophy", "correct": true}, {"label": "B", "text": "Cerebral Hypertrophy", "correct": false}, {"label": "C", "text": "Ventricular enlargement", "correct": false}, {"label": "D", "text": "Aqueductal stenosis", "correct": false}], "correct_answer": "A. Cerebral Atrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cerebral Atrophy From the age, history, MMSE score diagnosis- Alzheimer's disease . Alzheimer's disease (AD) is the most common cause of dementia in older adults , with an increasing incidence as a function of age . The disease usually becomes clinically apparent as an insidious impairment of higher cognitive functions . As the disease progresses, deficits in memory, visuospatial orientation, judgment, personality and language emerge . Typically over a course of 5 to 10 years, on MRI of patients, temporoparietal cortical atrophy, and hippocampus atrophy is seen .</p>\n<p><strong>Highyeild:</strong></p><p>The fundamental abnormality in Alzheimer's Disease is the accumulation of two proteins (Aβ and tau) in specific brain regions, likely as a result of excessive production and defective removal . Two pathologic hallmarks , particularly evident in the end stages of the illness, are amyloid plaques and neurofibrillary tangles . CSF findings: Tau increased Amyloid decreased Acetylcholine (Ach) is decreased in the Nucleus of Meyernet An increase in Apo E4 is a risk factor for Alzheimer’s Treatment: Central AchE antagonist: Donepezel, Rivastigmine, Galantamine NMDA Receptor antagonist: Mimantine</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Cerebral Hypertrophy. No, it’s cerebral atrophy, not hypertrophy which is seen in Alzheimer's disease. Option: C. Ventricular enlargement. Ventricles look relatively enlarged but not actually enlarged . Option: D. Aqueductal stenosis. Ventricular enlargement can be caused by aqueductal stenosis but here ventricles are enlarged relative to the brain parenchyma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 67-year-old man came to medicine OPD with complaints of headaches most of the time of the day. He is a chronic hypertensive and has diabetes for which he is not compliant. He has a Blood pressure of 180/110 and a heart rate of 89 beats per minute On auscultation bruit was heard on the right kidney. Intravenous pyelography and renal arteriography were done. Diagnosis of Right renal arteriosclerosis was made. What changes will be expected to occur in the right kidney?", "options": [{"label": "A", "text": "Dysplasia of the right kidney", "correct": false}, {"label": "B", "text": "Atrophy of the right kidney", "correct": true}, {"label": "C", "text": "Hypertrophy of the right kidney", "correct": false}, {"label": "D", "text": "Metaplasia of the right kidney", "correct": false}], "correct_answer": "B. Atrophy of the right kidney", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Atrophy of the right kidney Due to stenosis, of the right renal artery, there will be less blood flow to the right kidney . The ischemic kidney is reduced in size and shows signs of diffuse ischemic atrophy . Hypertension secondary to renal artery stenosis is caused by increased production of renin from the ischemic kidney . So, the correct answer is B. Atrophy of the right kidney.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Dysplasia of the right kidney. Renal artery stenosis doesn’t lead to Dysplasia. Option: C. Hypertrophy of the right kidney. Renal artery stenosis doesn’t lead to Hypertrophy. Option: D. Metaplasia of the right kidney. Renal artery stenosis doesn’t lead to Metaplasia.</p>\n<p><strong>Extraedge:</strong></p><p>The most common cause of renal artery stenosis (70% of cases) is narrowing at the origin of the renal artery by an atheromatous plaque . The ischemic kidney is reduced in size and shows signs of diffuse ischemic atrophy , with crowded glomeruli, atrophic tubules, interstitial fibrosis, and focal inflammatory infiltrates.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 65-year-old male was diagnosed with prostate cancer with metastatic disease. He passed away due to a sudden stroke. A gross specimen of his heart during autopsy is shown below. Which of the following statements is incorrect regarding this patient’s heart?", "options": [{"label": "A", "text": "Lipofuscin is composed of polymers of lipids and phospholipids in complex with protein", "correct": false}, {"label": "B", "text": "It is derived through lipid peroxidation of polyunsaturated lipids of intracellular membranes", "correct": false}, {"label": "C", "text": "Tell-tale sign of free radical injury and lipid peroxidation", "correct": false}, {"label": "D", "text": "In tissue sections, it appears as a yellow-brown, finely granular intranuclear pigment", "correct": true}], "correct_answer": "D. In tissue sections, it appears as a yellow-brown, finely granular intranuclear pigment", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812030312-QTDP005006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>In tissue sections, it appears as a yellow-brown, finely granular intranuclear pigment The specimen shows Brown atrophy in which the heart is small, with chocolate-brown myocardium . In this condition, there is excessive lipochrome (lipofuscin) deposition within the myocardial fibres . Ageing and malnutrition may favour this process, a form of cellular auto-phagocytosis . Antioxidants may protect against such injury . In the normal ageing process, the amount of lipofuscin increases within the myocardial fibre cytoplasm. In tissue sections , it appears as a yellow-brown, finely granular CYTOPLASMIC, often perinuclear, pigment . It is seen in cells undergoing slow, regressive changes and is particularly prominent in the liver and heart of ageing patients or patients with severe malnutrition and cancer cachexia .</p>\n<p><strong>Highyeild:</strong></p><p>Lipofuscin is an insoluble pigment, also known as lipochrome or wear-and-tear pigment. Lipofuscin is composed of polymers of lipids and phospholipids in complex with protein . It is derived through lipid peroxidation of polyunsaturated lipids of intracellular membranes . In tissue sections, it appears as a yellow-brown , finely granular cytoplasmic, often perinuclear pigment . It is a telltale sign of free radical injury and lipid peroxidation . It is seen in cells undergoing slow, regressive changes and is particularly prominent in the liver and heart of ageing patients or patients with severe malnutrition and cancer cachexia . NOTE: Lipofuscin is not injurious to the cell or its functions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A, B, C. All are correct.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The ultra-structural finding of irreversible injury:", "options": [{"label": "A", "text": "Ribosomal detachment from the endoplasmic reticulum", "correct": false}, {"label": "B", "text": "Large, flocculent, Amorphous densities in mitochondria", "correct": true}, {"label": "C", "text": "Formation of myelin figures", "correct": false}, {"label": "D", "text": "Cell swelling", "correct": false}], "correct_answer": "B. Large, flocculent, Amorphous densities in mitochondria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Large, flocculent, Amorphous densities in mitochondria Dead cells may be replaced by large, whorled phospholipid masses called myelin figures that are derived from damaged cell membranes. These phospholipid precipitates are then either phagocytosed by other cells or further degraded into fatty acids; calcification of such fatty acid residues results in the generation of calcium soaps . Thus, the dead cells may ultimately become calcified . By electron microscopy , necrotic cells are characterized by discontinuities in plasma and organelle membranes, marked dilation of mitochondria with the appearance of large amorphous densities, intracytoplasmic myelin figures, amorphous debris, and aggregates of fluffy material probably representing denatured protein. Nuclear change s appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis ) Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. With the passage of time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with a detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following statements is false regarding primary biliary cholangitis?", "options": [{"label": "A", "text": "It is an autoimmune disease", "correct": false}, {"label": "B", "text": "Primarily involve large intrahepatic ducts", "correct": true}, {"label": "C", "text": "95% of patients show anti-mitochondrial antibody", "correct": false}, {"label": "D", "text": "Elevated levels of serum ALP", "correct": false}], "correct_answer": "B. Primarily involve large intrahepatic ducts", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Primarily involve large intrahepatic ducts Primary biliary cholangitis (PBC) is a chronic autoimmune liver disease characterized by the progressive destruction of the intrahepatic bile ducts. The disease primarily affects the small intrahepatic bile duct s, not the large ones.</p>\n<p><strong>Highyeild:</strong></p><p>Primary biliary cholangiti Chronic autoimmune liver disease Classically seen with other autoimmune conditions: Hashimoto thyroiditis, Rheumatoid arthritis, celiac disease More common in females than males Symptoms: Jaundice, pruritus, osteopenia, portal hypertensio n Histopathology: Lymphocytic infiltrate Destruction of lobular bile ducts (small intrahepatic bile ducts) Ductopenia Florid duct lesions (Granuloma) seen -Diagnosis: Antimitochondrial antibody present Elevated alkaline phosphatase (ALP) Elevated γ-glutamyltransferase (GGT) -Treatment: Ursodeoxycholic acid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A, C, D: All are true</p>\n<p><strong>Table:</strong></p><p>Difference between Primary Biliary Cholangitis and Primary\n Sclerosing Cholangitis Primary Biliary Cholangitis Primary Sclerosing Cholangitis Incidence Females> Males Middle age Males > Females 20- 40 years of age Site of involvement Intrahepatic Intrahepatic and Extrahepatic Cause of obstruction Granulomatous inflammation destroying bile ducts Fibrosis destroy s bile ducts Microscopy Florid duct lesions (Granuloma?) Concentric onion-skin fibrosis around bile ducts Diagnosis AMA antibody positive MPO-ANCA/ P-ANCA positive The beaded appearance of bile ducts on ERCP Association other autoimmune disorders Ulcerative colitis (Hashimoto’s thyroiditis, S jogren 's )</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statement are true regarding primary sclerosing cholangitis:", "options": [{"label": "A", "text": "The most common antibody seen is pANCA", "correct": false}, {"label": "B", "text": "It is associated with ulcerative colitis", "correct": false}, {"label": "C", "text": "HPE shows circumferential onion skin fibrosis around the duct", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Primary sclerosing cholangitis is an immune mediated cholestatic disease. All the statements given above are true with respect to PSC. Hence, the correct option is D: All of the above.</p>\n<p><strong>Highyeild:</strong></p><p>Primary Sclerosing Cholangitis Sclerosing: as it causes scarring and thickening (sclerosis) of the bile ducts Cholangitis: it means inflammation of the bile ducts. It is an immune-mediated cholestatic liver disease. It is characterised by inflammation and fibrosis of both intrahepatic and extrahepatic bile ducts. It leads to the formation of multimodal bile duct strictures More common in males Histopathology: Shows circumferential onion skin fibrosis around the duct Atrophic duct lumen eventually leading to obliteration by a tombstone scar Diagnosis: MPO-ANCA/ P-ANCA positive The beaded appearance of bile duct s on ERCP Associated with Ulcerative colitis (70% of cases)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A.,B.,C. All are true regarding Primary sclerosing cholangitis.</p>\n<p><strong>Table:</strong></p><p>Difference between Primary Biliary Cholangitis and Primary Sclerosing Cholangitis Primary Biliary Cholangitis Primary Sclerosing Cholangitis Incidence Females> Males Middle age Males > Females 20- 40 years of age Site of involvement Intrahepatic Intrahepatic and Extrahepatic Cause of obstruction Granulomatous inflammation destroying bile ducts Fibrosis destroy s bile ducts Microscopy Florid duct lesions (Granuloma?) Concentric onion-skin fibrosis around bile ducts Diagnosis AMA antibody positive MPO-ANCA/ P-ANCA positive The beaded appearance of bile ducts on ERCP Association other autoimmune disorders Ulcerative colitis (Hashimoto’s thyroiditis, S jogren 's )</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 54-year-old patient presented with jaundice( raised direct bilirubin) and the presence of a pANCA antibody. The liver biopsy is shown below. What is your diagnosis?", "options": [{"label": "A", "text": "Primary biliary cirrhosis", "correct": false}, {"label": "B", "text": "Primary sclerosing cholangitis", "correct": true}, {"label": "C", "text": "Hepatolithiasis", "correct": false}, {"label": "D", "text": "Biliary atresia", "correct": false}], "correct_answer": "B. Primary sclerosing cholangitis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157720957-QTDP123004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Primary sclerosing cholangitis The given clinical scenario with a histopathological image of liver biopsy showing onion skin fibrosis is suggestive of primary sclerosing cholangitis (PSC)</p>\n<p><strong>Highyeild:</strong></p><p>Primary Sclerosing Cholangitis Sclerosing: as it causes scarring and thickening (sclerosis) of the bile ducts Cholangitis: means inflammation of the bile ducts. It is an immune-mediated cholestatic liver disease. It is characterised by inflammation and fibrosis of both intrahepatic and extrahepatic bile ducts. It leads to the formation of multimodal bile duct strictures More common in males Histopathology: Shows circumferential onion skin fibrosis around the duct Atrophic duct lumen eventually leading to obliteration by a tombstone scar Diagnosis: MPO-ANCA/ P-ANCA positive The beaded appearance of bile duct s on ERCP Associated with Ulcerative colitis (70% of cases)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Primary biliary cirrhosis: It typically presents with elevated levels of anti-mitochondrial antibodies, chronic cholestasis, and a characteristic histopathological finding of granulomatous destruction of small intrahepatic bile ducts. Option: C. Hepatolithiasis: It is a condition in which stones are present in the intrahepatic bile ducts. Option: D. Biliary atresia: It is a rare condition in which the bile ducts inside or outside the liver are damaged or absent, leading to bile flow obstruction and subsequent liver damage. It typically presents in infants with jaundice and acholic stools.</p>\n<p><strong>Table:</strong></p><p>Difference between Primary Biliary Cholangitis and Primary Sclerosing Cholangitis Primary Biliary Cholangitis Primary Sclerosing Cholangitis Incidence Females> Males Middle age Males > Females 20- 40 years of age Site of involvement Intrahepatic Intrahepatic and Extrahepatic Cause of obstruction Granulomatous inflammation destroying bile ducts Fibrosis destroy s bile ducts Microscopy Florid duct lesions (Granuloma?) Concentric onion-skin fibrosis around bile ducts Diagnosis AMA antibody positive MPO-ANCA/ P-ANCA positive The beaded appearance of bile ducts on ERCP Association other autoimmune disorders Ulcerative colitis (Hashimoto’s thyroiditis, S jogren 's )</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the mentioned antibodies are seen in type 1 autoimmune hepatitis except", "options": [{"label": "A", "text": "Anti-smooth muscle actin (SMA)", "correct": false}, {"label": "B", "text": "Antinuclear antibody", "correct": false}, {"label": "C", "text": "Anti-mitochondrial antibody", "correct": false}, {"label": "D", "text": "Anti LKM 1", "correct": true}], "correct_answer": "D. Anti LKM 1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anti LKM 1 Anti-LKM 1 antibody is not seen in Autoimmune hepatitis type 1 . It Is seen in Type 2 autoimmune hepatitis.</p>\n<p><strong>Highyeild:</strong></p><p>Autoimmune hepatitis Autoimmune hepatitis is a chronic autoimmune liver disease that is characterized by inflammation and damage to liver cells. It leads to cirrhosis and liver failure Associated with HLA-B1, HLA-B8, HLA-DR3, HLA-DR4 Histopathology: Extensive interface hepatitis (inflammation at the interface between hepatocytes and the portal tract), Plasma cell infiltrates , Presence of hepatic rosettes (clusters of hepatocytes that surround a central bile duct)</p>\n<p><strong>Extraedge:</strong></p><p>TYPE 1 AIH TYPE 2 AIH Antibodies Anti-SMA, ANA, pANCA, and antibodies anti-SLA Anti LKM1, anti-liver cytoskeleton 1 Incidence ● Bimodal: peaks at 10-20 years and 45-70 years ● 78% females ● 2-14 years ● 89% females IgG Pronouncedly increased Moderate increase IgA Absent Occasional Association HLA B8, DR3, DR4 HLA B14, DR3</p>\n<p><strong>Table:</strong></p><p>Antibodies in hepatitis Disease Antibodies Autoimmune hepatitis type 1 ANA, ASMA, pANCA, anti-AMA, anti-SLA Autoimmune hepatitis type 2 Anti-liver cytosol 1, Anti-LKM1 Drug - induced hepatitis Anti-LKM 2 Chronic hepatitis C Anti-LKM 1 Chronic hepatitis D Anti-LKM 3</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are histological features of autoimmune hepatitis?", "options": [{"label": "A", "text": "Extensive interface hepatitis", "correct": false}, {"label": "B", "text": "Plasma cell infiltrate", "correct": false}, {"label": "C", "text": "Hepatocyte rosette", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above All of the statements given above are true with respect to histological findings of autoimmune hepatitis. Hence, the correct option is D. All of the above.</p>\n<p><strong>Highyeild:</strong></p><p>Autoimmune hepatitis Autoimmune hepatitis is a chronic autoimmune liver disease that is characterized by inflammation and damage to liver cells. It leads to cirrhosis and liver failure Associated with HLA-B1, HLA-B8, HLA-DR3, HLA-DR4 Histopathology: Extensive interface hepatitis (inflammation at the interface between hepatocytes and the portal tract), Plasma cell infiltrates , Presence of hepatic rosettes (clusters of hepatocytes that surround a central bile duct)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Extensive interface hepatitis: Interface hepatitis refers to the inflammation at the interface between the hepatocytes (liver cells) and the portal tracts. Option: B. Plasma cell infiltrate: Autoimmune hepatitis is known to exhibit a significant infiltration of plasma cells.These plasma cells are involved in the production of antibodies that target liver cells, contributing to the autoimmune response. Option: C. Hepatocyte rosette: These are a specific histological feature observed in autoimmune hepatitis. They are characterized by hepatocytes forming concentric circles around the central vein, resembling a rosette-like pattern. This pattern is thought to be a result of the immune-mediated destruction of hepatocytes.</p>\n<p><strong>Extraedge:</strong></p><p>TYPE 1 AIH TYPE 2 AIH Antibodies Anti-SMA, ANA, pANCA, anti-AMA, anti-SLA Anti LKM1, anti-liver cytoskeleton 1 Incidence ● Bimodal: peaks at 10-20 years and 45-70 years ● 78% females ● 2-14 years ● 89% females IgG Pronouncedly increased Moderate increase IgA Absent Occasional Association HLA B8,DR3,DR4 HLA B14, DR3</p>\n<p><strong>Table:</strong></p><p>Antibodies\n in hepatitis Disease Antibodies Autoimmune hepatitis type 1 ANA, ASMA, pANCA, anti-AMA, anti-SLA Autoimmune hepatitis type 2 Anti-liver cytosol 1, Anti-LKM1 Drug - induced\n hepatitis Anti-LKM 2 Chronic hepatitis C Anti-LKM 1 Chronic hepatitis D Anti-LKM 3</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Platelet adhesion to the vessel wall is due to the:", "options": [{"label": "A", "text": "Factor IX", "correct": false}, {"label": "B", "text": "Fibrinogen", "correct": false}, {"label": "C", "text": "vWF", "correct": true}, {"label": "D", "text": "Fibronectin", "correct": false}], "correct_answer": "C. vWF", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>vWF Platelet adhesion to the vessel wall is due to the von Willebrand Factor (vWF) on endothelium and GpIb/IX receptors on the surface of platelets.</p>\n<p><strong>Highyeild:</strong></p><p>In the pathogenesis of Myocardial infarction, the following sequence of events is seen: Disruption/Erosion of Atherosclerotic plaque Platelet adhesion Microthrombi formation Endothelium releases Tissue Factor Secondary plug formation (thrombus formed) Thrombus occludes/blocks the vessel Myocardial infarction Myocardial Infarction (MI), also commonly referred to as “heart attack,” is the death of cardiac muscle due to prolonged ischemia. An atheromatous plaque is eroded or suddenly disrupted by endothelial injury , intraplaque haemorrhage, or mechanical forces, exposing subendothelial collagen and necrotic plaque contents to the blood. Platelets adhere, aggregate, and are activated, releasing thromboxane A2, adenosine diphosphate (ADP), and serotonin—causing further platelet aggregation and vasospasm. Activation of coagulation by tissue factors and other mechanisms adds to the growing thrombus. Within minutes, the thrombus can evolve to completely occlude the coronary artery lumen. The sequence of events in a typical MI also has therapeutic implications: Early thrombolysis and/or angioplasty can be highly successful in limiting the extent of myocardial necrosis Some occlusions can clear spontaneously through lysis of the thrombus or relaxation of spasm .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Factor IX. Incorrect . Option: B. Fibrinogen. Incorrect . Option: D. Fibronectin. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a component of the dense granules of platelets?", "options": [{"label": "A", "text": "ADP", "correct": false}, {"label": "B", "text": "Calcium", "correct": false}, {"label": "C", "text": "Epinephrine", "correct": false}, {"label": "D", "text": "Platelet factor 4", "correct": true}], "correct_answer": "D. Platelet factor 4", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Platelet factor 4 Dense (or delta) granules of platelets contain: A den osine diphosphate (ADP) E pinephrine S erotonin Calcium Alpha granules of platelets contain: Factor V, VIII Platelet factor 4 PDGF Fibrinogen</p>\n<p><strong>Highyeild:</strong></p><p>In pathogenesis of Myocardial infarction, the following sequence of events is seen: Disruption/Erosion of Atherosclerotic plaque Platelet adhesion Microthrombi formation Endothelium releases Tissue Factor Secondary plug formation (thrombus formed) Thrombus occludes/blocks the vessel Myocardial infarction Myocardial Infarction (MI), also commonly referred to as “heart attack,” is the death of cardiac muscle due to prolonged ischemia. An atheromatous plaque is eroded or suddenly disrupted by endothelial injury , intraplaque haemorrhage, or mechanical forces, exposing subendothelial collagen and necrotic plaque contents to the blood. Platelets adhere, aggregate, and are activated, releasing thromboxane A2, adenosine diphosphate (ADP), and serotonin—causing further platelet aggregation and vasospasm. Activation of coagulation by tissue factors and other mechanisms adds to the growing thrombus. Within minutes, the thrombus can evolve to completely occlude the coronary artery lumen. The sequence of events in a typical MI also has therapeutic implications: Early thrombolysis and/or angioplasty can be highly successful in limiting the extent of myocardial necrosis Some occlusions can clear spontaneously through lysis of the thrombus or relaxation of spasm .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A, B & C are Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The earliest event of vascular trauma is:", "options": [{"label": "A", "text": "Vasoconstriction", "correct": true}, {"label": "B", "text": "Platelet adhesion", "correct": false}, {"label": "C", "text": "Platelet aggregation", "correct": false}, {"label": "D", "text": "Vasodilatation", "correct": false}], "correct_answer": "A. Vasoconstriction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Vasoconstriction Endothelial injury causes vasoconstriction (due to endothelin, serotonin ) immediately and markedly reduces blood flow to the injured area .</p>\n<p><strong>Highyeild:</strong></p><p>In the pathogenesis of Myocardial infarction, the following sequence of events is seen: Disruption/Erosion of Atherosclerotic plaque Platelet adhesion Microthrombi formation Endothelium releases Tissue Factor Secondary plug formation (thrombus formed) Thrombus occludes/blocks the vessel Myocardial infarction Myocardial Infarction (MI), also commonly referred to as “heart attack,” is the death of cardiac muscle due to prolonged ischemia. An atheromatous plaque is eroded or suddenly disrupted by endothelial injury , intraplaque haemorrhage, or mechanical forces, exposing subendothelial collagen and necrotic plaque contents to the blood. Platelets adhere, aggregate, and are activated, releasing thromboxane A2, adenosine diphosphate (ADP), and serotonin—causing further platelet aggregation and vasospasm. Activation of coagulation by tissue factors and other mechanisms adds to the growing thrombus. Within minutes, the thrombus can evolve to completely occlude the coronary artery lumen. The sequence of events in a typical MI also has therapeutic implications: Early thrombolysis and/or angioplasty can be highly successful in limiting the extent of myocardial necrosis Some occlusions can clear spontaneously through lysis of the thrombus or relaxation of spasm .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Platelet adhesion. Incorrect . Option: C. Platelet aggregation. Incorrect . Option: D. Vasodilatation. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a qualitative defect of platelet?", "options": [{"label": "A", "text": "VWD", "correct": false}, {"label": "B", "text": "Hemophilia A", "correct": false}, {"label": "C", "text": "Hemophilia C", "correct": false}, {"label": "D", "text": "Glanzmann thrombasthenia", "correct": true}], "correct_answer": "D. Glanzmann thrombasthenia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Glanzmann thrombasthenia Glanzmann thrombasthenia is a qualitative defect of platelet in which there is a platelet aggregation defect.</p>\n<p><strong>Highyeild:</strong></p><p>Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. VWD. Deficiency of vWF . Option: B. Hemophilia A. Deficiency of Factor VIII . Option: C. Hemophilia C. Deficiency of Factor XI .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "PDGF is present in which granules of platelets?", "options": [{"label": "A", "text": "Alpha", "correct": true}, {"label": "B", "text": "Beta", "correct": false}, {"label": "C", "text": "Delta", "correct": false}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "A. Alpha", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Alpha Alpha granules of platelets contain: Factor V, VIII Platelet factor 4 PDGF Fibrinogen Dense (or delta) granules of platelets contain: A den osine diphosphate (ADP) E pinephrine S erotonin Calcium</p>\n<p><strong>Highyeild:</strong></p><p>In the pathogenesis of Myocardial infarction, the following sequence of events is seen: Disruption/Erosion of Atherosclerotic plaque Platelet adhesion Microthrombi formation Endothelium releases Tissue Factor Secondary plug formation (thrombus formed) Thrombus occludes/blocks the vessel Myocardial infarction Myocardial Infarction (MI), also commonly referred to as “heart attack,” is the death of cardiac muscle due to prolonged ischemia. An atheromatous plaque is eroded or suddenly disrupted by endothelial injury , intraplaque haemorrhage, or mechanical forces, exposing subendothelial collagen and necrotic plaque contents to the blood. Platelets adhere, aggregate, and are activated, releasing thromboxane A2, adenosine diphosphate (ADP), and serotonin—causing further platelet aggregation and vasospasm. Activation of coagulation by tissue factors and other mechanisms adds to the growing thrombus. Within minutes, the thrombus can evolve to completely occlude the coronary artery lumen. The sequence of events in a typical MI also has therapeutic implications: Early thrombolysis and/or angioplasty can be highly successful in limiting the extent of myocardial necrosis Some occlusions can clear spontaneously through lysis of the thrombus or relaxation of spasm .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Beta. Incorrect . Option: C. Delta. Incorrect . Option: D. None. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In von Willebrand's disease, what is true?", "options": [{"label": "A", "text": "Ristocetin aggregation test is decreased", "correct": true}, {"label": "B", "text": "Ristocetin aggregation is Increased", "correct": false}, {"label": "C", "text": "No effect", "correct": false}, {"label": "D", "text": "May be increased or decreased", "correct": false}], "correct_answer": "A. Ristocetin aggregation test is decreased", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ristocetin aggregation test is decreased Ristocetin cofactor assa y/Ristocetin-induced platelet aggregation is decreased or absent in vWD</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Ristocetin aggregation is Increased. Incorrect . Option: C. No effect. Incorrect . Option: D. May be increased or decreased. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An adolescent female presents with palpable purpura. Her hemogram suggested only anaemia. What is your diagnosis?", "options": [{"label": "A", "text": "ITP", "correct": false}, {"label": "B", "text": "TTP", "correct": false}, {"label": "C", "text": "HUS", "correct": false}, {"label": "D", "text": "HSP", "correct": true}], "correct_answer": "D. HSP", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>HSP Henoch Scholein Purpura (HSP) presents as palpable purpura . HSP is a systemic vasculitis that affects small vessels, including those in the skin, gastrointestinal tract, and kidneys. Palpable purpura , which is caused by leakage of blood into the skin, is the hallmark clinical feature of HSP . Anaemia is a less common finding in HSP and is thought to be related to gastrointestinal blood loss .</p>\n<p><strong>Highyeild:</strong></p><p>Most common condition associated with palpable purpura is cutaneous small-vessel vasculitis or leukocytoclastic vasculitis (LCV) . Henoch-Schönlein Purpura (HSP): Most common vascularised in children: HSP > Kawasaki A subtype of acute LCV mainly seen in children & adolescents, following upper respiratory infection . The majority of lesions are found on the lower extremities and buttocks . Systemic manifestations include fever , arthralgias , abdominal pain , GI bleeding , and nephritis . Direct immunofluorescence examination shows deposits of IgA within dermal blood vessel walls . Renal disease is of particular concern in adults with HSP . Tetrad of HSP: IgA Nephropathy Arthritis Colic type of abdominal pain Palpable purpura with Thrombocytosis Treatment: Steroids</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. ITP. Immune Thrombocytopenic Purpura is caused by autoantibody-mediated destruction of platelets, Thrombocytopenia , rather than anaemia and typically lacks the palpable purpura seen in HSP . Option: B. TTP. Thrombotic thrombocytopenic purpura (TTP) and hemolytic uremic syndrome (HUS) are both associated with microangiopathic hemolytic anaemia, in addition to thrombocytopenia and organ dysfunction , but typically lack the palpable purpura seen in HSP . Option: C. HUS. Thrombotic thrombocytopenic purpura (TTP) and hemolytic uremic syndrome (HUS) are both associated with microangiopathic hemolytic anaemia, in addition to thrombocytopenia and organ dysfunction , but typically lack the palpable purpura seen in HSP .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In Bernard Soulier syndrome there is a defect in:", "options": [{"label": "A", "text": "Platelet Aggregation", "correct": false}, {"label": "B", "text": "Platelet Adhesion", "correct": true}, {"label": "C", "text": "Platelet activation", "correct": false}, {"label": "D", "text": "Platelet agglutination", "correct": false}], "correct_answer": "B. Platelet Adhesion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Platelet Adhesion In Bernard Soulier syndrome there is a platelet adhesion defect due to Absence of Gp Ib-IX-V receptor.</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Platelet Aggregation. Incorrect, seen with Glanzmann Thrombasthenia . Option: C. Platelet activation. Incorrect . Option: D. Platelet agglutination. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 7-year-old boy presented with sudden onset petechiae and purpura. There was a history of URTI 2 weeks back. On examination, there was no hepatosplenomegaly. He is most probably suffering from", "options": [{"label": "A", "text": "ALL", "correct": false}, {"label": "B", "text": "Acute viral infection", "correct": false}, {"label": "C", "text": "ITP", "correct": true}, {"label": "D", "text": "Aplastic Anemia", "correct": false}], "correct_answer": "C. ITP", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>ITP A 7-year-old boy presented with sudden onset petechiae and purpura with a history of URTI 2 weeks back and there is no hepatosplenomegaly . He is most probably suffering from ITP.</p>\n<p><strong>Highyeild:</strong></p><p>Immune Thrombocytopenic Purpura: Acute ITP Acute ITP is mainly a disease of childhood occurring with equal frequency in both sexes . Symptoms appear abruptly, often 1 to 2 weeks after a self-limited viral illness, which appears to trigger the development of autoantibodies through uncertain mechanisms . Unlike chronic ITP, acute ITP is self-limited , usually resolving spontaneously within 6 months . Glucocorticoids are given only if the thrombocytopenia is severe . In about 20% of children, usually those without a viral prodrome, thrombocytopenia persists; these children have a childhood form of chronic ITP that follows a course similar to the adult disease Chronic ITP Chronic ITP is caused by the autoantibody-mediated destruction of platelets . Etiology: Idiopathic (Immune) Secondary Autoimmune diseases Viral infections Autoantibodies , most often directed against platelet membrane glycoproteins IIb–IIIa or Ib–IX , can be demonstrated in the plasma and bound to the platelet surface in about 80% of patients. As in autoimmune hemolytic anaemias, antiplatelet antibodies act as opsonins that are recognized by IgG Fc receptors expressed on phagocytes, leading to increased platelet destruction . Thrombocytopenia is usually markedly improved by splenectomy , indicating that the spleen is the major site of removal of opsonized platelets, but the spleen is of normal size . The marrow reveals a modestly increased number of megakaryocytes . The secondary changes relate to haemorrhage, often in the form of petechial bleeds into the skin and mucous membranes . The peripheral blood often reveals abnormally large platelets (mega thrombocytes), which are a sign of accelerated thrombopoiesis. Occurs most commonly in adult women younger than 40 years of age. The female-to-male ratio is 3:1 There is a history of easy bruising, nosebleeds, gingival bleeding, and haemorrhages into soft tissues from relatively minor trauma. Almost all patients respond to glucocorticoids (which inhibit phagocyte function), but many relapses following the withdrawal of steroids.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. ALL. For diagnosis of ALL Lymphoblast>20% should be present in peripheral smear. Option: B. Acute viral infection. Sudden onset petechiae and purpura and history of URTI 2 weeks back, rule out acute viral infection. Option: D. Aplastic Anemia. Bone marrow cellularity < 25% of Hematopoietic cells go in favour of aplastic ana</p>\n<p><strong>Table:</strong></p><p>Causes of Thrombocytopenia Decreased Production of Platelets Selective impairment of platelet production Drug-induced: alcohol, thiazides,\n cytotoxic drugs Infections: measles, human immunodeficiency virus (HIV)\n Nutritional deficiencies B₁₂, folate deficiency (megaloblastic leukemia) Aplastic anemia (see Table 14.7) Bone marrow replacement Leukemia, disseminated cancer, granulomatous disease Ineffective hematopoiesis Myelodysplastic syndromes (Chapter 13) Decreased Platelet Survival Immunologic destruction Chromic immune thrombocytopenic purpura Acute immune thrombocytopenic\n purpura Systemic lupus erythematosus, B-cell lymphoid neoplasms Alloimmune:\n posttransfusion and neonatal Infections: HIV, infectious mononucleosis\n (transient, mild), dengue Drug-associated: quinidine, heparin, sulfa compounds fever Nonimmunologic destruction Disseminated intravascular coagulation Thrombotic microangiopathies Giant hemangiomas Sequestration Hypersplenism Dilution Transfusions</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Platelet aggregation is caused by:", "options": [{"label": "A", "text": "Nitrous oxide", "correct": false}, {"label": "B", "text": "Thromboxane A2", "correct": true}, {"label": "C", "text": "Aspirin", "correct": false}, {"label": "D", "text": "PGE2", "correct": false}], "correct_answer": "B. Thromboxane A2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thromboxane A2</p>\n<p><strong>Highyeild:</strong></p><p>Thromboxane A2 (TXA2) It is produced by activated platelets and has prothrombotic properties It is an Arachidonic acid metabolite of the COX pathway Functions: It is a potent platelet aggregator & vasoconstrictor Its effect is neutralized by prostacyclin (PGI2) Normal hemostasis. (A) After vascular injury, neurohumoral factors induce transient vasoconstriction. (B) Platelets bind via glycoprotein lb (Gplb) receptors to von Willebrand factor (vWF) on exposed extracellular matrix (ECM) and are activated, undergoing a shape change and granule release. Released adenosine diphosphate (ADP) and thromboxane A2 (TxA2) induce additional platelet aggregation through platelet Gpllb-llla receptor binding to fibrinogen, and form the primary hemostatic plug. (C) Local activation of the coagulation cascade (involving tissue factor and platelet phospholipids) results in fibrin polymerization, \"cementing\" the platelets into a definitive secondary hemostatic plug.(D) Counterregulatory mechanisms, mediated by tissue plasminogen activator (t-PA, a fibrinolytic product) and thrombomodulin, confine the hemostatic process to the site of injury. Activated platelets also produce prostaglandin thromboxane A2 (TxA2 ), a potent inducer of platelet aggregation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option A,C,D Don’t cause platelet aggregation.</p>\n<p><strong>Table:</strong></p><p>Principal Actions of Arachidonic Acid Metabolites\n in Inflammation Action Eicosanoid Vasodilation Prostaglandins PGI 2 (prostacyclin), PGE 1 , PGE 2 , PGD 2 Vasoconstriction Thromboxane A 2 , leukotrienes C 4 , D 4 , E 4 Increased vascular permeability Leukotrienes C 4 , D 4 , E 4 Chemotaxis, leukocyte adhesion Leukotrienes B 4 , HETE</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Glanzman’s disease is-", "options": [{"label": "A", "text": "Congenital defect of platelets", "correct": true}, {"label": "B", "text": "Congenital defect of RBCs", "correct": false}, {"label": "C", "text": "Defect of neutrophils", "correct": false}, {"label": "D", "text": "Clotting factor deficiency", "correct": false}], "correct_answer": "A. Congenital defect of platelets", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Congenital defect of platelets Glanzmann's disease is a congenital defect of platelets</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Congenital defect of RBCs. Incorrect . Option: C. Defect of neutrophils. Incorrect . Option: D. Clotting factor deficiency. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All the following conditions cause thrombocytopenia except", "options": [{"label": "A", "text": "Giant hemangioma", "correct": false}, {"label": "B", "text": "Infectious mononucleosis", "correct": false}, {"label": "C", "text": "HIV infection", "correct": false}, {"label": "D", "text": "Iron deficiency anaemia", "correct": true}], "correct_answer": "D. Iron deficiency anaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Iron deficiency anaemia Thrombocytopenia refers to platelet count < 1.5 lac/cu mm Q Thrombocytopenia is seen in 50% of patients with Infectious Mononucleosis Thrombocytosis is seen in Iron deficiency Anemia , platelet counts rise to twice the normal value and return to normal with Iron therapy . The exact cause is unknown, but probably due to increased levels of Erythropoietin.</p>\n<p><strong>Highyeild:</strong></p><p>Pathogenesis of Infectious Mononucleosis : EBV causes infectious mononucleosis , a benign, self-limited lymphoproliferative disorder , and is associated with the pathogenesis of several human tumours, most commonly certain lymphomas and nasopharyngeal carcinoma . Infectious mononucleosis is characterized by fever, sore throat, generalized lymphadenopathy, splenomegaly, and the appearance in the blood of atypical activated T lymphocytes (mononucleosis cells). Some people develop hepatitis, meningoencephalitis, and pneumonitis. Infectious mononucleosis occurs principally in late adolescents or young adults among upper socioeconomic classes in higher-income nations. In the rest of the world, primary infection with EBV occurs in childhood and is usually asymptomatic. EBV is transmitted by close human contact, frequently through saliva during kissing . It is not known whether the source of the virus is B cells, oropharyngeal epithelial cells, or both EBV infects B cells and possibly epithelial cells of the oropharynx. It has been hypothesized that EBV initially infects oropharyngeal epithelial cells and then spreads to underlying lymphoid tissue (tonsils and adenoids), where mature B cells are infected. An EBV envelope glycoprotein binds CD21 (CR2) , the receptor for the C3d component of complement , which is present in B cells . DOWNEY cells are atypical CD8+ T lymphocytes that are characteristic of infectious mononucleosis . DOWNY cells exhibit both suppressor & cytotoxic functions that develop in response to the infected B lymphocytes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Giant hemangioma. Giant hemangioma is a benign vascular tumour that can cause thrombocytopenia by trapping platelets within the tumour. Option: B. Infectious mononucleosis. Infectious mononucleosis is caused by the Epstein-Barr virus and can lead to thrombocytopenia due to both decreased platelet production and increased platelet destruction. Option: C. HIV infection. HIV infection can cause thrombocytopenia through several mechanisms, including decreased platelet production, increased platelet destruction, and autoimmune platelet destruction.</p>\n<p><strong>Extraedge:</strong></p><p>Of note, people with X-linked agammaglobulinemia, who lack B cells , do NOT become latently infected with EBV or shed virus , suggesting that B cells are the main reservoir of infection</p>\n<p><strong>Table:</strong></p><p>Causes\n of Thrombocytopenia Decreased\n Production of Platelets Selective\n impairment of platelet production Drug-induced: alcohol, thiazides, cytotoxic\n drugs Infections: measles, human immunodeficiency virus (HIV) Nutritional\n deficiencies B₁₂,\n folate deficiency (megaloblastic leukemia) Aplastic\n anemia (see Table 14.7) Bone\n marrow replacement Leukemia,\n disseminated cancer, granulomatous disease Ineffective\n hematopoiesis Myelodysplastic\n syndromes (Chapter 13) Decreased\n Platelet Survival Immunologic\n destruction Chromic\n immune thrombocytopenic purpura Acute immune thrombocytopenic purpura\n Systemic lupus erythematosus, B-cell lymphoid neoplasms Alloimmune:\n posttransfusion and neonatal Infections: HIV, infectious mononucleosis\n (transient, mild), dengue Drug-associated:\n quinidine, heparin, sulfa compounds fever Nonimmunologic\n destruction Disseminated\n intravascular coagulation Thrombotic\n microangiopathies Giant\n hemangiomas Sequestration Hypersplenism Dilution Transfusions</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "vWF is useful in:", "options": [{"label": "A", "text": "Platelet adhesion", "correct": true}, {"label": "B", "text": "Platelet aggregation", "correct": false}, {"label": "C", "text": "Clot formation", "correct": false}, {"label": "D", "text": "Fibrinolysis", "correct": false}], "correct_answer": "A. Platelet adhesion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Platelet adhesion 2 major functions of vWF are: Platelet adhesion via GpIb/IX and Stabilizes factor VIII in circulation.</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Platelet aggregation Incorrect . Option: C. Clot formation. Incorrect . Option: D. Fibrinolysis. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Fever, fluctuating neurological symptoms, renal failure and severe thrombocytopenia are characteristic of-", "options": [{"label": "A", "text": "Hemolytic uremic syndrome", "correct": false}, {"label": "B", "text": "Thrombotic thrombocytopenic purpura", "correct": true}, {"label": "C", "text": "Idiopathic thrombocytopenic purpura", "correct": false}, {"label": "D", "text": "Disseminated intravascular coagulation", "correct": false}], "correct_answer": "B. Thrombotic thrombocytopenic purpura", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thrombotic thrombocytopenic purpura</p>\n<p><strong>Highyeild:</strong></p><p>Thrombotic thrombocytopenic purpura TTP is caused by a deficiency in a plasma enzyme called ADAMTS13 , also designated “vWF metalloprotease.” ADAMTS13 degrades very high-molecular-weight multimers of vWF . In its absence, large multimers accumulate in plasma and tend to promote spontaneous platelet activation and aggregation . ADAMTS13 deficiency may be inherited or acquired . In the acquired form, an autoantibody that inhibits the metalloprotease activity of ADAMTS13 is present . Less commonly , patients inherit an inactivating mutation in ADAMTS13 . TTP was defined as the pentad of fever, thrombocytopenia, microangiopathic hemolytic an a emia, transient neurologic deficits, and renal failure . HUS also is associated with microangiopathic hemolytic an a emia and thrombocytopenia but is distinguished by the absence of neurologic symptoms, the prominence of acute renal failure, and its frequent occurrence in children . Typical HUS is strongly associated with infectious gastroenteritis caused by Escherichia coli strain O157:H7 , which elaborates a Shiga-like toxin . Thrombotic Microangiopathies: Causes and Associations Thrombotic Thrombocytopenic Purpura Deficiency of ADAMTS13 Inherited Acquired (autoantibodies) Hemolytic Uremic Syndrome Typical: Escherichia coli strain O157:H7 infection Endothelial damage by Shiga-like toxin Atypical: alternative complement pathway inhibitor -deficiencies (complement factor H, membrane cofactor protein [CD46], or factor 1) -Inherited -Acquired (autoantibodies) Miscellaneous associations -Drugs (cyclosporine, chemotherapeutic agents) -Radiation, bone marrow transplantation -Other infections (HIV, pneumococcal sepsis) -Conditions associated with autoimmunity (systemic lupus erythematosus, HIV infection, lymphoid neoplasms) HIV, Human immunodeficiency virus. In both conditions, intravascular thrombi cause microangiopathic hemolytic anaemia and widespread organ dysfunction, and the attendant consumption of platelets leads to thrombocytopenia . In TTP and HUS (unlike in DIC), activation of the coagulation cascade is not of primary importance, and hence laboratory tests of coagulation, such as the PT and PTT, are usually normal .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hemolytic uremic syndrome. Typical HUS is strongly associated with infectious gastroenteritis caused by Escherichia coli strain O157:H7 , which elaborates a Shiga-like toxin . Option: C. Idiopathic thrombocytopenic purpura. Caused by autoantibody-mediated destruction of platelets, there is a history of easy bruising, nosebleeds, gingival bleeding, and haemorrhages into soft tissues from relatively minor trauma. Option: D. Disseminated intravascular coagulation. DIC is an acute, subacute, or chronic thrombohemorrhagic disorder characterized by the excessive activation of coagulation and the formation of thrombi in the microvasculature .</p>\n<p><strong>Extraedge:</strong></p><p>Treatment: Steroids i/v Ig Plasma Exchange/Plasmapheresis cause to Reduce Antibodies to ADAMTS13 Plasma Transfusion is used for the Replenishment of ADAMTS13</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "After a tonsillectomy, a 9-year-old child is having continuous bleeding. Bleeding time and PTT are prolonged. Platelet count and PT are normal. What is the likely diagnosis?", "options": [{"label": "A", "text": "Von Willebrand disease", "correct": true}, {"label": "B", "text": "Vitamin K deficiency", "correct": false}, {"label": "C", "text": "Immune thrombocytopenic purpura", "correct": false}, {"label": "D", "text": "Hemophilia A", "correct": false}], "correct_answer": "A. Von Willebrand disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Von Willebrand disease Bleeding time and aPTT prolonged PT and platelet count normal</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Vitamin K deficiency. False, PT prolonged . Option: C. Immune thrombocytopenic purpura. False, aPTT is normal . Option: D. Hemophilia A. False, Bleeding time normal .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "True regarding heparin-induced thrombocytopenia:", "options": [{"label": "A", "text": "Platelet counts usually < 10,000/uL", "correct": false}, {"label": "B", "text": "Increased risk of thrombosis", "correct": true}, {"label": "C", "text": "Associated with severe bleeding", "correct": false}, {"label": "D", "text": "HIT antibodies disappear in 5-14 days", "correct": false}], "correct_answer": "B. Increased risk of thrombosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increased risk of thrombosis HIT is a prothrombotic state .</p>\n<p><strong>Highyeild:</strong></p><p>Heparin Induced Thrombocytopenia (HIT) HIT syndrome is a serious, potentially life-threatening disorder that occurs following the administration of unfractionated heparin . Heparin is a Hapten, e. an incomplete antigen, and when it combines with Platelet Factor 4 (PF4) , it becomes a complete antigen and can lead to the formation of antibodies. PF4 usually is present on the platelet surface . Thheparin-induced combines with this Heparin-PF4 complex on the platelet surface. This is followed by fibrin binding to this complex and forming a clot . This effect on platelets and endothelial damage induced by antibody binding combine to produce a prothrombotic state , even in the face of heparin administration and low platelet counts (as platelets are deposited in the thrombus thus formed). Thus there is Thrombocytopenia which is induced by heparin . This is seen after 4-14 days of heparin exposure .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Platelet counts usually < 10,000/uL. False, Thrombocytopenia (decrease of > 50% ) . Option: C. Associated with severe bleeding. False, Bleeding is uncommon in HIT . Option: D. HIT antibodies disappear in 5-14 days. False, they appear after 5-14 days .</p>\n<p><strong>Extraedge:</strong></p><p>Treatment of HIT: Heparin should be discontinued in such cases. Even low molecular weight (LMW) heparins are not safe in such patients, and they should be treated with a direct thrombin inhibitor. Drugs used in the treatment of HIT include Bivalirudin Argatroban</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A five-year-old child presents with oliguria. There is a history of bloody diarrhoea 2 weeks ago. Coagulation tests are normal. A peripheral smear is given. What is your diagnosis?", "options": [{"label": "A", "text": "Thrombotic thrombocytopenic purpura", "correct": false}, {"label": "B", "text": "Idiopathic thrombocytopenic purpura", "correct": false}, {"label": "C", "text": "G6PD deficiency", "correct": false}, {"label": "D", "text": "Hemolytic uremic syndrome", "correct": true}], "correct_answer": "D. Hemolytic uremic syndrome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686830792236-QTDP086018IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemolytic uremic syndrome Features of oliguria following an episode of dysentery with peripheral smear finding of Schistocytes (Helmet cells) are suggestive of Hemolytic uremic syndrome .</p>\n<p><strong>Highyeild:</strong></p><p>Hemolytic Uremic Syndrome Typical HUS is strongly associated with infectious gastroenteritis caused by Escherichia coli strain O157:H7 , which elaborates a Shiga-like toxin . This toxin is absorbed from the inflamed gastrointestinal mucosa into the circulation, where it is believed to directly or indirectly alter endothelial cell functio n in some manner that provokes platelet activation and aggregation . Children and older adults are at highest risk . Those affected present with bloody diarrhoea , and a few days later HUS makes its appearance. Atypical HUS is often associated with defects in complement factor H, membrane cofactor protein (CD46), or factor I , proteins that act to prevent excessive activation of the alternative complement pathway . Deficiencies of these proteins may be caused by inherited defects or acquired inhibitory autoantibodies and are associated with a remitting, relapsing clinical course . Immunosuppression also may be beneficial to patients with inhibitory autoantibodies. Typical HUS is treated supportively .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Thrombotic thrombocytopenic purpura. Incorrect , Child with a history of bloody diarrhoea 2 weeks ago now comes with oliguria and schistocytes in the peripheral smear are suggestive of HUS . TTP is caused by a deficiency in a plasma enzyme called ADAMTS13 . Option: B. Idiopathic thrombocytopenic purpura. Incorrect , ITP is caused by autoantibody-mediated destruction of platelets . Option: C. G6PD deficiency. Incorrect , In patients with G6PD , symptoms usually resolve when the triggering factor is removed. Intermittent episodes of hemolysis triggered by certain drugs, infections, or foods (Fava beans). In severe cases, hemolysis can be acute, causing jaundice, dark urine, and abdominal pain Peripheral smear findings in G6PD deficiency may include the presence of Heinz bodies and bite cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following is not a platelet function test", "options": [{"label": "A", "text": "Bleeding time", "correct": false}, {"label": "B", "text": "Prothrombin time", "correct": true}, {"label": "C", "text": "Clot retraction time", "correct": false}, {"label": "D", "text": "Prothrombin consumption index", "correct": false}], "correct_answer": "B. Prothrombin time", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Prothrombin time Prothrombin time assesses extrinsic pathway of coagulation</p>\n<p><strong>Highyeild:</strong></p><p>Coagulation test: Prothrombin Time 12-16 sec Activated Partial Thromboplastin Time 28-35 sec Measure EP + CP IP + CP Sample PPP {Platelet Poor Plasma} PPP Add in Thromboplastin Ca + PL Kaolin Ca + PL 1. ↑ PT Normal APTT - Extrinsic Pathway defect; Factor VII deficiency: Vit-K deficiency: Warfarin II. Norml PT ↑ APTT Intrinsic Pathway deficiency: Factor XII, XI, IX, VIII deficiency; Von Willebrand Disease III. 1PT ↑ APTT - Common Pathway defect: Factor X, V, II, I deficiency: Severe Liver disease; DIC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Bleeding time. Bleeding time assesses the ability of platelets to form a platelet plug . Option: C. Clot retraction time. Clot retraction study measures the time taken for a platelet plug to undergo the last step of retraction, which indicates overall platelet function . Option: D. Prothrombin consumption index. An abnormal Prothrombin consumption index indicates impaired availability of platelet membrane phospholipid for coagulation .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "True about von Willebrand disease:", "options": [{"label": "A", "text": "aPTT is normal", "correct": false}, {"label": "B", "text": "Bleeding time is normal", "correct": false}, {"label": "C", "text": "The most common pattern of inheritance is autosomal recessive", "correct": false}, {"label": "D", "text": "Bleeding from the mucosa in the oral cavity may present", "correct": true}], "correct_answer": "D. Bleeding from the mucosa in the oral cavity may present", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bleeding from the mucosa in the oral cavity may present True, mucosal bleeding is seen in vWD . The most common presenting symptom s are spontaneous bleeding from mucous membranes (e.g., epistaxis), excessive bleeding from wounds, or menorrhagia .</p>\n<p><strong>Highyeild:</strong></p><p>Von Willebrand Disease: Von Willebrand disease is the most common inherited bleeding disorder of humans . The bleeding tendency is usually mild and often goes unnoticed until some hemostatic stress, such as surgery or a dental procedure, reveals its presence. The most common presenting symptom s are spontaneous bleeding from mucous membranes (e.g., epistaxis), excessive bleeding from wounds, or menorrhagia . It is usually transmitted as an autosomal dominant disorder , but rare autosomal recessive variants also exist. 3 types are recognised: Type 1 and type 3 von Willebrand disease are associated with quantitative defects in vWF . Type 1 , is an autosomal dominant disorder characterized by a mild to moderate vWF deficiency. Type 3 disease is an autosomal disorde r usually caused by deletions or frameshift mutations involving both alleles, resulting in little to no vWF synthesis . Because vWF stabilizes factor VIII in the circulation , factor VIII levels are also reduced in type 3 disease and the associated bleeding disorder is often severe . Type 2 von Willebrand disease is characterized by qualitative defects in vWF . It is inherited as an autosomal dominant disorder . Patients with von Willebrand disease have defects in platelet function despite having normal platelet counts . The plasma level of active vWF, measured as the ristocetin cofactor activity, is reduced . Persons with types 1 or 2 von Willebrand disease facing hemostatic challenges (dental work, surgery) can be treated with desmopressin (which stimulates vWF release), infusions of plasma concentrates containing factor VIII and vWF , or with recombinant vWF . By contrast, rare patients with type 3 disease must be treated prophylactically with plasma concentrates and factor VIII infusions to prevent severe “haemophilia-like” bleeding.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. aPTT is normal. False, vWF stabilises factor VIII , which takes part in the Intrinsic pathway . So, in vWD, when vWF is deficient, aPTT is prolonged. Option: B. Bleeding is normal. False, because there is defective platelet adhesion in vWD, there is an increase in bleeding time . Option: C. Most common pattern of inheritance is autosomal recessive. False, the most common pattern of inheritance is Autosomal dominant for vWD type I.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A newborn baby presented with profuse bleeding from the umbilical stump after birth. The rest of the examination and PT, APTT are within normal limits. The most probable diagnosis is-", "options": [{"label": "A", "text": "Factor X deficiency", "correct": false}, {"label": "B", "text": "Glanzmann thrombasthenia", "correct": true}, {"label": "C", "text": "Von Willebrand disease", "correct": false}, {"label": "D", "text": "Factor VIII deficiency", "correct": false}], "correct_answer": "B. Glanzmann thrombasthenia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Glanzmann thrombasthenia A newborn baby presented with profuse bleeding from the umbilical stump after birth . This is a case of severe inherited bleeding disorder. As PT & apTT are normal , Glanzmann thrombasthenia is the most probable cause, which can present with profuse bleeding soon after birth . It can be diagnosed by platelet aggregation studies , which will be defective . The other differential diagnosis in this scenario is Factor XIII deficiency (not given in the Option:).</p>\n<p><strong>Highyeild:</strong></p><p>Glanzmann thrombasthenia exemplifies bleeding due to defective platelet aggregation . It is transmitted as an autosomal recessive trait . Thrombasthenic platelets fail to aggregate in response to adenosine diphosphate (ADP), collagen, epinephrine, or thrombin because of deficiency or dysfunction of glycoprotein IIb–IIIa , an integrin that participates in “bridge formation” between platelets by binding fibrinogen. The associated bleeding tendency is often severe .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Factor X deficiency. False, Factor X is involved in the common pathway of the coagulation cascade, thus both PT and aPTT will be prolonged . Option: C. Von Willebrand disease. False, Normal PT and prolonged aPTT . Option: D. Factor VIII deficiency. False, Normal PT and prolonged aPTT .</p>\n<p><strong>Extraedge:</strong></p><p>Drugs mimicking Glanzmann thrombasthenia or Anti GP IIb/IIIa drugs: Abciximab Tirofiban Ebtifibatide These are the strongest-acting antiplatelets and are injectable drugs.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What abnormalities will be present in a patient having deficiency of Von Willebrand factor?", "options": [{"label": "A", "text": "Increased apTT, increased- PT", "correct": false}, {"label": "B", "text": "Decreased.PT, increased apTT", "correct": false}, {"label": "C", "text": "Normal PT, Normal apTT", "correct": false}, {"label": "D", "text": "Normal PT, increased aPTT", "correct": true}], "correct_answer": "D. Normal PT, increased aPTT", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Normal PT, increased aPTT In vWD, there is Normal PT, increased a PTT vWF stabilizes factor VIII , which takes part in the i ntrinsic pathway . So in vWD, when vWF is deficient, the i ntrinsic pathway of coagulation is affecte d , giving rise to prolonged apTT ; but as the extrinsic pathway is not affected, PT remains normal .</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Increased apTT, Increased- PT. Incorrect . Option: B. Decreased. PT, Increased apTT. Incorrect . Option: D. Normal PT, Normal apTT. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is not true regarding Bernard Soulier syndrome?", "options": [{"label": "A", "text": "Ristocetin aggregation is normal", "correct": true}, {"label": "B", "text": "Aggregation with collagen and ADP is normal", "correct": false}, {"label": "C", "text": "Large platelets", "correct": false}, {"label": "D", "text": "Thrombocytopenia", "correct": false}], "correct_answer": "A. Ristocetin aggregation is normal", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ristocetin aggregation is normal False, Ristocetin aggregation is absent .</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Aggregation with collagen and ADP is normal: True, as GpIIb/IIIa involved in these aggregates is normal . Option: C. Large platelets. True, as giant platelets are a feature of Bernard–Soulier syndrome . Option: D. Thrombocytopenia. True, Mild thrombocytopenia may be seen.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements about platelet function defects is true?", "options": [{"label": "A", "text": "Normal platelet count with prolonged bleeding time", "correct": true}, {"label": "B", "text": "Thrombocytopenia with prolonged bleeding time", "correct": false}, {"label": "C", "text": "Thrombocytosis with prolonged bleeding time", "correct": false}, {"label": "D", "text": "Normal platelet count with normal bleeding time", "correct": false}], "correct_answer": "A. Normal platelet count with prolonged bleeding time", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Normal platelet count with prolonged bleeding time In platelet function defects, there is a normal platelet count with prolonged bleeding time .</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Thrombocytopenia with prolonged bleeding time. Incorrect . Option: C. Thrombocytosis with prolonged bleeding time. Incorrect . Option: D. Normal platelet count with normal bleeding time. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "25 yr old asymptomatic female underwent pre-op coagulation testing. Her BT was 3 minutes, PT was 15/14 seconds, and aPTT 45/35 seconds. Platelet counts were 2.5 lac/uL, and factor VIII levels were 60 IU/dl. The most likely diagnosis is:", "options": [{"label": "A", "text": "Factor IX deficiency", "correct": false}, {"label": "B", "text": "vWD type 3", "correct": false}, {"label": "C", "text": "Factor VIII inhibitor", "correct": true}, {"label": "D", "text": "Lupus anticoagulant", "correct": false}], "correct_answer": "C. Factor VIII inhibitor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor VIII inhibitor This is the case of an asymptomatic female with normal BT, PT & platelet counts ; aPTT is increased , and factor VIII levels (N=50-150 IU/dl) are near normal . A factor VIII inhibitor is an antibody that targets and inactivates factor VIII , a protein that is critical for blood clotting. In individuals with haemophilia A, which is caused by a deficiency in factor VIII, the immune system can sometimes produce these inhibitors as a result of treatment with factor VIII replacement therapy . The development of inhibitors can reduce the effectiveness of factor VIII therapy and make it more difficult to control bleeding.</p>\n<p><strong>Highyeild:</strong></p><p>table,tr,th,td {border:1px solid black;} Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Factor IX deficiency. Also called as Haemophilia B , ruled out as the patient in the question is asymptomatic and Factor IX deficiency leads to clinical bleeding. Option: B. vWD type 3. Ruled out as in the question, the patient is asymptomatic and BT is normal. Option: D. Lupus anticoagulant. The second best answer, as isolated aPTT in an asymptomatic female can be due to Lupus anticoagulant. However, usually, the patient presents with thrombocytopenia and prolonged PT .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Thrombocytopenia due to increased platelet destruction is seen in -", "options": [{"label": "A", "text": "Aplastic anaemia", "correct": false}, {"label": "B", "text": "Cancer chemotherapy", "correct": false}, {"label": "C", "text": "Acute leukaemia", "correct": false}, {"label": "D", "text": "Systemic lupus erythematosus", "correct": true}], "correct_answer": "D. Systemic lupus erythematosus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Systemic lupus erythematosus Thrombocytopenia due to platelet destruction is seen in SLE</p>\n<p><strong>Highyeild:</strong></p><p>Causes of Thrombocytopenia Decreased Production of Platelets Selective impairment of platelet production Drug-induced: alcohol, thiazides, cytotoxic drugs Infections: measles, human immunodeficiency virus (HIV) Nutritional deficiencies B 12 . folate deficiency (megaloblastic leukemia) Aplastic anemia Bone marrow replacement Leukemia, disseminated cancer, granulomatous disease Ineffective hematopoiesis Myelodysplastic syndromes (Chapter 13) Decreased Platelet Survival Immunologic destruction Chromic immune thrombocytopenic purpura Acute immune thrombocytopenic purpura Systemic lupus erythematosus, B-cell lymphoid neoplasms Alloimmune: posttransfusion and neonatal Drug-associated: quinidine, heparin, sulfa compounds Infections: HIV, infectious mononucleosis (transient, mild), dengue fever Nonimmunologic destruction Disseminated intravascular coagulation Thrombotic microangiopathies Giant hemangiomas Sequestration Hypersplenism Dilution Transfusions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Aplastic ana Causes thrombocytopenia due to decreased platelet production . Option: B. Cancer chemotherapy. Causes thrombocytopenia due to decreased platelet production . Option: C. Acute leuka Causes thrombocytopenia due to decreased platelet production .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 35 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Identify the disorder in which destruction of smooth muscle and elastic tissue by chronic necrotizing infections leads to permanent dilation of bronchi and bronchioles:", "options": [{"label": "A", "text": "Emphysema", "correct": false}, {"label": "B", "text": "Asthma", "correct": false}, {"label": "C", "text": "Chronic bronchitis", "correct": false}, {"label": "D", "text": "Bronchiectasis", "correct": true}], "correct_answer": "D. Bronchiectasis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bronchiectasis Bronchiectasis is a condition in which there is permanent dilation of bronchi and bronchioles due to the destruction of smooth muscle and elastic tissue by chronic necrotizing infections.</p>\n<p><strong>Highyeild:</strong></p><p>Bronchiectasis It is a chronic condition characterized by the permanent dilation and distortion of the bronchi and bronchioles due to necrotizing infections, leading to impaired mucociliary clearance and chronic inflammation. Causes: Recurrent respiratory infections (e.g. pneumonia, tuberculosis, pertussis), Cystic fibrosis, Immunodeficiency disorders, and genetic disorders (e.g. primary ciliary dyskinesia ). Pathogenesis: Symptoms: Chronic cough with the production of copious amounts of sputum, Hemoptysis , Recurrent respiratory infections, Dyspnea, chest pain, and fatigue. Digital clubbing Diagnosis: It is usually based on clinical history, physical examination, chest imaging, pulmonary function tests, and sputum culture. Treatment: The goals of treatment for bronchiectasis include controlling infections, improving lung function, and reducing symptoms.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Emphysema : It is a condition in which there is destruction of the alveolar walls and enlargement of air spaces. Option: B. Asthma : It is a chronic inflammatory disease of the airways characterized by bronchial hyperresponsiveness and reversible airflow obstruction. Option: C. Chronic bronchitis: It is a type of COPD characterized by chronic inflammation of the bronchi and excessive mucus production.</p>\n<p><strong>Extraedge:</strong></p><p>Histopathological Findings of Bronchiectasis Dilatation of bronchi and bronchioles Destruction of the bronchial wall Chronic inflammation of the bronchial wall with a predominance of neutrophils and lymphocytes Fibrosis and scarring of the bronchial wall Hypertrophy and hyperplasia of mucus-secreting glands in the bronchial wall Accumulation of purulent exudate, mucus, and debris in the bronchi Epithelial metaplasia, with replacement of ciliated columnar cells by squamous cells Smooth muscle hypertrophy and hyperplasia of bronchial walls</p>\n<p><strong>Table:</strong></p><p>Types Description Cylindrical Dilated bronchi with straight and usually regular\n outline Tram-track lines parallel to each other Signet ring appearance when seen in the axial plane Cystic or Saccular The ballooned appearance of bronchi may have air-fluid levels; large,\n cystic areas with a honeycomb appearance Varicose Bronchi with dilated segments and other areas of\n constriction; beaded bronchi</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding primary ciliary dyskinesia except:", "options": [{"label": "A", "text": "It is X-linked syndrome", "correct": true}, {"label": "B", "text": "Occurs due to mutation involving dynein protein", "correct": false}, {"label": "C", "text": "It is also associated with Kartagener syndrome", "correct": false}, {"label": "D", "text": "Males are infertile", "correct": false}], "correct_answer": "A. It is X-linked syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is X-linked syndrome Primary ciliary dyskinesia (PCD) is not an X-linked syndrome, but rather an autosomal recessive disorder .</p>\n<p><strong>Highyeild:</strong></p><p>Primary ciliary dyskinesia It is a genetic disorder that affects the structure and function of cilia in the respiratory tract , causing chronic respiratory infections and other complications. Inheritance: autosomal recessive with a frequency of 1 in 15,000 to 40,000 births, Cayse: Mutations in genes that affect the structure or function of dynein arms , which are essential for the movement of cilia. Features: PCD can lead to chronic respiratory infections, chronic sinusitis, and bronchiectasis due to impaired clearance of mucus and debris from the airways. It is o ften associated with Kartagener syndrome , which is a rare disorder that involves a triad of symptoms: situs inversus, chronic sinusitis, and bronchiectasis.</p>\n<p><strong>Extraedge:</strong></p><p>Kartagener's syndrome It is also known as immotile cilia syndrome, A rare, ciliopathic, autosomal recessive genetic disorder Characterized by a defect in the action of the cilia lining the respiratory tract (lower and upper, sinuses, Eustachian tube, and middle ear) and fallopian tube. Triad: Dextrocardia, Sinusitis, Bronchiectasis. Young's Syndrome Defect in ciliary function with unknown mechanism Characterized by: Sinusitis, Obstructive azoospermia, and Bronchiectasis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old male presents to the clinic with a chronic cough and recurrent respiratory infections. On examination, there are crackles heard on auscultation. A CT scan shows permanent dilation of bronchi and bronchioles. All of the following features are true regarding the diagnosis except:", "options": [{"label": "A", "text": "Inflammatory exudation within bronchial walls", "correct": false}, {"label": "B", "text": "Desquamation of the lining epithelium", "correct": false}, {"label": "C", "text": "Areas of ulceration", "correct": false}, {"label": "D", "text": "Squamous Metaplasia is not a feature", "correct": true}], "correct_answer": "D. Squamous Metaplasia is not a feature", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Squamous Metaplasia is not a feature The given clinical feature is suggestive of Bronchiectasis. Squamous metaplasia , which is the transformation of the normal respiratory epithelium into squamous epithelium, is a feature of bronchiectasis. It is a response to chronic inflammation and irritation and can further contribute to the damage and dilation of the bronchi.</p>\n<p><strong>Highyeild:</strong></p><p>Bronchiectasis It is a chronic condition characterized by the permanent dilation and distortion of the bronchi and bronchioles due to necrotizing infections, leading to impaired mucociliary clearance and chronic inflammation. Causes: Recurrent respiratory infections (e.g. pneumonia, tuberculosis, pertussis), Cystic fibrosis, Immunodeficiency disorders, and genetic disorders (e.g. primary ciliary dyskinesia ). Pathogenesis: Symptoms: Chronic cough with the production of copious amounts of sputum, Hemoptysis , Recurrent respiratory infections, Dyspnea, chest pain, and fatigue. Digital clubbing Diagnosis: It is usually based on clinical history, physical examination, chest imaging, pulmonary function tests, and sputum culture. Treatment: The goals of treatment for bronchiectasis include controlling infections, improving lung function, and reducing symptoms.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Inflammatory exudation within bronchial walls:-This is true and a hallmark feature of bronchiectasis. Chronic inflammation and infection lead to the accumulation of inflammatory cells, mucus, and cellular debris within the walls of the bronchi and bronchioles, causing their permanent dilation. Option: B. Desquamation of the lining epithelium: This is also a true feature of bronchiectasis. The chronic inflammatory process damages the lining epithelium of the bronchi, leading to desquamation or shedding of the cells. Option: C. Areas of ulceration - This is true as well. Chronic inflammation and infection can cause areas of necrosis and ulceration in the walls of the bronchi, which can further contribute to the permanent dilation.</p>\n<p><strong>Extraedge:</strong></p><p>Histopathological Findings of Bronchiectasis Dilatation of bronchi and bronchioles Destruction of the bronchial wall Chronic inflammation of the bronchial wall with a predominance of neutrophils and lymphocytes Fibrosis and scarring of the bronchial wall Hypertrophy and hyperplasia of mucus-secreting glands in the bronchial wall Accumulation of purulent exudate, mucus, and debris in the bronchi Epithelial metaplasia, with replacement of ciliated columnar cells by squamous cells Smooth muscle hypertrophy and hyperplasia of bronchial walls</p>\n<p><strong>Table:</strong></p><p>Types Description Cylindrical Dilated bronchi with straight and usually regular outline Tram-track lines parallel to each other Signet ring appearance when seen in the axial plane Cystic or Saccular The ballooned appearance of bronchi may have air-fluid levels; large, cystic areas with a honeycomb appearance Varicose Bronchi with dilated segments and other areas of constriction; beaded bronchi</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All are true about CLL except:", "options": [{"label": "A", "text": "Most common Leukaemia of adults in the west", "correct": false}, {"label": "B", "text": "Can transform to DLBCL", "correct": false}, {"label": "C", "text": "Most common mutation is deletion 13q", "correct": false}, {"label": "D", "text": "Most common age group is pediatric", "correct": true}], "correct_answer": "D. Most common age group is pediatric", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Most common age group is pediatric False, most commonly it is seen in the adult population i.e. above 60 yrs.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Lymphocytic Leukaemia (CLL)/ Small Lymphocytic Lymphoma (SLL): CLL is the most common Leukaemia in adults in the Western world . The median age at diagnosis is 60 years , and there is a 2:1 male predominance . Microscopy: Lymph nodes are diffusely effaced by predominantly small lymphocytes called Pseudofollicular architecture with proliferation centres . Peripheral smear: Smudge cells Chronic lymphocytic leukemia. This peripheral blood smear is flooded with small lymphocytes with condensed chromatin and scant cytoplasm. A characteristic finding is the presence of disrupted tumor cells (smudge cells), two of which are present in this smear. A coexistent autoimmune hemolytic anemia (Chapter 14) explains the presence of spherocytes (hyperchromatic, round erythrocytes). A nucleated erythroid cell is present in the lower left-hand corner of the field. In this setting, circulating nucleated red cells could stem from premature release of progenitors in the face of severe anemia, marrow infiltration by tumor (leukoerythroblastosis), or both. Mutation: Chromosome 13q deletion Immunohistochemistry: CD5 +, CD23 +, CD19 +, CD 20+ Transformation to diffuse large B-cell lymphoma (DLBCL), is called Richter syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Most common Leukaemia of adults in the west. True . Option: B. Can transform to DLBCL. True, called Richter syndrome . Option: C. Most common mutation is deletion 13q. True . REMEMBER: Whenever in a question two Option:s go against each other, either of them is likely to be the answer, e.g. in this question Option:s A and D go against each other, thus giving you a hint that either of them is likely to be the answer .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old male presents with generalized lymphadenopathy and hepatosplenomegaly. Immunophenotype: CD5, CD23+ and CD19 are positive and CD10 negative. Diagnosis:", "options": [{"label": "A", "text": "Follicular lymphoma", "correct": false}, {"label": "B", "text": "Burkitt lymphoma", "correct": false}, {"label": "C", "text": "Hairy cell leukaemia", "correct": false}, {"label": "D", "text": "CLL", "correct": true}], "correct_answer": "D. CLL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CLL Only CD5 + tumours are CLL and Mantle zone lymphoma.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Lymphocytic Leukaemia (CLL)/ Small Lymphocytic Lymphoma (SLL): CLL is the most common leukaemia in adults in the Western world . The median age at diagnosis is 60 years , and there is a 2:1 male predominance . Microscopy: Lymph nodes are diffusely effaced by predominantly small lymphocytes called Pseudofollicular architecture with proliferation centres . Peripheral smear: Smudge cells Chronic lymphocytic leukemia. This peripheral blood smear is flooded with small lymphocytes with condensed chromatin and scant cytoplasm. A characteristic finding is the presence of disrupted tumor cells (smudge cells), two of which are present in this smear. A coexistent autoimmune hemolytic anemia (Chapter 14) explains the presence of spherocytes (hyperchromatic, round erythrocytes). A nucleated erythroid cell is present in the lower left-hand corner of the field. In this setting, circulating nucleated red cells could stem from premature release of progenitors in the face of severe anemia, marrow infiltration by tumor (leukoerythroblastosis), or both. Mutation: Chromosome 13q deletion Immunohistochemistry: CD5 +, CD23 +, CD19 +, CD 20+ Transformation to diffuse large B-cell lymphoma (DLBCL), is called Richter syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Follicular lymphoma. CD10 +, CD19+, CD 20+ . Option: B. Burkitt lymphoma. CD10 +, CD19+, CD 20+ . Option: C. Hairy cell leukaemia. CD11c +, CD 25 +, CD 103 +, FMC 7 + .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An elderly male presents with anaemia and fatigue. O/E is splenomegaly-2 cm palpable below the costal margin. Hemogram showed Pancytopenia. Which is the most common etiology?", "options": [{"label": "A", "text": "Hairy cell leukaemia", "correct": true}, {"label": "B", "text": "CML", "correct": false}, {"label": "C", "text": "Thalassemia", "correct": false}, {"label": "D", "text": "Follicular lymphoma", "correct": false}], "correct_answer": "A. Hairy cell leukaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hairy cell leukaemia In the given scenario an elderly male presents with Anemia , Splenomegaly & Pancytopenia .</p>\n<p><strong>Highyeild:</strong></p><p>Hairy cell Leukaemia Chronic B-cell leukaemia is characterized by hairy cells, pancytopenia and splenomegaly Median age: 55 years M:F ratio of 5:1 Splenomegaly , often massive, is the most common and sometimes the only abnormal physical finding . Excellent prognosis. Mutation: BRAF Microscopy: Leukemic cells , which have fine hair-like projections that are best recognized under the phase-contrast microscope. The marrow is involved by a diffuse interstitial infiltrate of cells with oblong or reniform nuclei , condensed chromatin, and pale cytoplasm. Because these cells are enmeshed in an extracellular matrix composed of reticulin fibrils , they usually are inseparable (a clinical difficulty referred to as a “ dry tap ”) and are seen only in marrow biopsies. The biopsy shows a Fried egg appearance . Stains used: TRAP, Annexin A1 . Markers: CD11c +, CD 25 +, CD 103 +, FMC 7 + . Hairy cell leukemia (peripheral blood smear). (A) Phase-contrast microscopy shows tumor cells with fine hairlike cytoplasmic projections. (B) In stained smears, these cells have round or folded nuclei and modest amounts of pale blue, agranular cytoplasm.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. CML. Massive splenomegaly with Leukocytosis (increase in leukocytes) and basophilia is seen Option: C. Thalassemia. Jaundice, severe anaemia (requiring transfusion), and hepatosplenomegaly with leukoerythroblastosis , are usually present in childhood . Option: D. Follicular lymphoma. Lymphadenopathy ± Leukocytosis (Leukopenia not seen).</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mantle cell lymphomas are positive for all of the following, except -", "options": [{"label": "A", "text": "CD23", "correct": true}, {"label": "B", "text": "CD20", "correct": false}, {"label": "C", "text": "CD5", "correct": false}, {"label": "D", "text": "CD45", "correct": false}], "correct_answer": "A. CD23", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD23 Mantle cell lymphomas are negative for CD 23 Only CD5 + tumours are CLL and Mantle zone lymphoma.</p>\n<p><strong>Highyeild:</strong></p><p>Mantle Cell Lymphoma: It usually presents in the fifth to sixth decades of life and shows a male predominance . As the name implies, the tumour cells closely resemble the normal mantle zone B cells that surround germinal centres. Translocation: t(11;14) Overexpression of the BCL protein: BCL2 is overexpressed It is CD5+ and CD23− , which help to distinguish it from CLL/SLL . Nodal tumour cells may surround reactive germinal centres to produce a nodular appearance at low power or diffusely efface the node. Typically, the proliferation consists of a homogeneous population of small lymphocytes with irregular to occasionally deeply cleft (cleaved) nuclear contours . Mantle cell lymphoma. (A) At low power, neoplastic lymphoid cells surround a small, atrophic germinal center, producing a mantle zone pattern of growth. (B) High-power view shows a homogeneous population of small lymphoid cells with somewhat irregular nuclear outlines, condensed chromatin, and scant cytoplasm. Large cells resembling prolymphocytes (seen in chronic lymphocytic leukemia) and centroblasts (seen in follicular lymphoma) are absent.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. CD20. Positive , as the Mantle cell is B-cell derived . Option: C. CD5. Positive , as the Mantle cell is derived from the Mantle zone of the Lymph node. Option: D. CD45. Positive , as CD 45 is a marker for WBCs.</p>\n<p><strong>Extraedge:</strong></p><p>Mantle cell lymphoma is Cyclin D1 and BCL 1 positive, if Cyclin D1 is negative then Mantle cell lymphoma will be SOX 11 positive .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about Mantle cell lymphoma except:", "options": [{"label": "A", "text": "Associated with (11;14) translocation", "correct": false}, {"label": "B", "text": "Overexpression of the BCL protein", "correct": false}, {"label": "C", "text": "CD 5 positive", "correct": false}, {"label": "D", "text": "CD 23 positive", "correct": true}], "correct_answer": "D. CD 23 positive", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD 23 positive Mantle cell lymphomas are negative for CD 23 Only CD5 + tumours are CLL and Mantle zone lymphoma .</p>\n<p><strong>Highyeild:</strong></p><p>Mantle Cell Lymphoma: It usually presents in the fifth to sixth decades of life and shows a male predominance . As the name implies, the tumour cells closely resemble the normal mantle zone B cells that surround germinal centres. Translocation: t(11;14) Overexpression of the BCL protein: BCL2 is overexpressed It is CD5+ and CD23− , which help to distinguish it from CLL/SLL . Nodal tumour cells may surround reactive germinal centres to produce a nodular appearance at low power or diffusely efface the node. Typically, the proliferation consists of a homogeneous population of small lymphocytes with irregular to occasionally deeply cleft (cleaved) nuclear contours . Mantle cell lymphoma. (A) At low power, neoplastic lymphoid cells surround a small, atrophic germinal center, producing a mantle zone pattern of growth. (B) High-power view shows a homogeneous population of small lymphoid cells with somewhat irregular nuclear outlines, condensed chromatin, and scant cytoplasm. Large cells resembling prolymphocytes (seen in chronic lymphocytic leukemia) and centroblasts (seen in follicular lymphoma) are absent.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Associated with (11;14) translocation. True . Option: B. Overexpression of the BCL protein. True . Option: C. CD 5 positive. True .</p>\n<p><strong>Extraedge:</strong></p><p>Mantle cell lymphoma is Cyclin D1 and BCL 1 positive, if Cyclin D1 is negative then Mantle cell lymphoma will be SOX 11 positive .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 48-year-old woman was admitted with a history of weakness for two months. On examination, cervical lymph nodes were found enlarged and the spleen was palpable 2 cm below the costal margin. Her haemoglobin was 10.5 g/dl, platelet counts 27 X 109 / L and total leukocyte count 40 X 109 / L, which included 80 % mature lymphoid cells with coarsely clumped chromatin. Bone marrow revealed a nodular lymphoid infiltrate. The peripheral blood lymphoid cells were positive for CD19, CD5, CD20 and CD23 and were negative for CD 79B and FMC-7. The histopathological examination of the lymph node in this patient will most likely exhibit effacement of lymph node architecture by -", "options": [{"label": "A", "text": "A pseudo follicular pattern with proliferation centres", "correct": true}, {"label": "B", "text": "A monomorphic lymphoid proliferation with a nodular pattern", "correct": false}, {"label": "C", "text": "A predominantly follicular pattern", "correct": false}, {"label": "D", "text": "A diffuse proliferation of medium to large lymphoid cells with a high mitotic rate", "correct": false}], "correct_answer": "A. A pseudo follicular pattern with proliferation centres", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>A pseudo follicular pattern with proliferation centres This is a case of a middle-aged female with lymphadenopathy, splenomegaly and peripheral blood lymphoid cells that were positive for CD19, CD5, CD20 and CD23 and negative for CD 79B and FMC-7 . This scenario is suggestive of a diagnosis of Chronic lymphocytic leukaemia (CLL) . In CLL, lymph node biopsy is suggestive of a pseudo follicular pattern with proliferation centres .</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Lymphocytic Leukaemia (CLL)/ Small Lymphocytic Lymphoma (SLL): CLL is the most common leukaemia in adults in the Western world . The median age at diagnosis is 60 years , and there is a 2:1 male predominance . Microscopy: Lymph nodes are diffusely effaced by predominantly small lymphocytes called Pseudofollicular architecture with proliferation centres . Peripheral smear: Smudge cells Caused by the decrease in Vimentin May predict a good prognosis Seen mainly in CLL; Also have been reported in AML, CML, ALL & the normal peripheral smear, but rare. Chronic lymphocytic leukemia. This peripheral blood smear is flooded with small lymphocytes with condensed chromatin and scant cytoplasm. A characteristic finding is the presence of disrupted tumor cells (smudge cells), two of which are present in this smear. A coexistent autoimmune hemolytic anemia (Chapter 14) explains the presence of spherocytes (hyperchromatic, round erythrocytes). A nucleated erythroid cell is present in the lower left-hand corner of the field. In this setting, circulating nucleated red cells could stem from premature release of progenitors in the face of severe anemia, marrow infiltration by tumor (leukoerythroblastosis), or both. Mutation: Chromosome 13q deletion Immunohistochemistry: CD5 +, CD23 +, CD19 +, CD 20+ Transformation to diffuse large B-cell lymphoma (DLBCL), is called Richter syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. A monomorphic lymphoid proliferation with a nodular pattern. False, seen in Follicular Lymphoma . Option: C. A predominantly follicular pattern. False, seen in Follicular Lymphoma . Option: D. A diffuse proliferation of medium to large lymphoid cells with a high mitotic rate. False, In CLL lymph nodes show a low mitotic rate .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 63-year-old man presented with massive splenomegaly, lymphadenopathy and a total leucocyte count of 17,000 per mm3. The flow cytometry showed CD 23 negative and CD 5 positive monoclonal B cells with bright kappa positively, comprising 80% of the peripheral blood lymphoid cells. The most likely diagnosis is -", "options": [{"label": "A", "text": "Mantle cell lymphoma", "correct": true}, {"label": "B", "text": "Splenic lymphoma with villous lymphocytes", "correct": false}, {"label": "C", "text": "Follicular lymphoma", "correct": false}, {"label": "D", "text": "Hairy cell leukaemia", "correct": false}], "correct_answer": "A. Mantle cell lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mantle cell lymphoma This is a case of an elderly male, who presented with massive splenomegaly, lymphadenopathy with lymphocytosis. Immunophenotyping shows CD5+ but CD23- which is suggestive of Mantle Zone Lymphoma . Mantle cell lymphomas are negative for CD 23 Only CD5 + tumours are CLL and Mantle zone lymphoma .</p>\n<p><strong>Highyeild:</strong></p><p>Mantle Cell Lymphoma It usually presents in the fifth to sixth decades of life and shows a male predominance . As the name implies, the tumour cells closely resemble the normal mantle zone B cells that surround germinal centres. Translocation: t(11;14) Overexpression of the BCL protein: BCL2 is overexpressed It is CD5+ and CD23− , which help to distinguish it from CLL/SLL . Nodal tumour cells may surround reactive germinal centres to produce a nodular appearance at low power or diffusely efface the node. Typically, the proliferation consists of a homogeneous population of small lymphocytes with irregular to occasionally deeply cleft (cleaved) nuclear contours . Mantle cell lymphoma. (A) At low power, neoplastic lymphoid cells surround a small, atrophic germinal center, producing a mantle zone pattern of growth. (B) High-power view shows a homogeneous population of small lymphoid cells with somewhat irregular nuclear outlines, condensed chromatin, and scant cytoplasm. Large cells resembling prolymphocytes (seen in chronic lymphocytic leukemia) and centroblasts (seen in follicular lymphoma) are absent.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Splenic lymphoma with villous lymphocytes. False . Option: C. Follicular lymphoma. False , CD 5 -ve, CD 10 +ve . Option: D. Hairy cell leukaemia. False , CD11c +ve, CD 25 +ve, CD 103 +ve, FMC 7 +ve .</p>\n<p><strong>Extraedge:</strong></p><p>Mantle cell lymphoma is Cyclin D1 and BCL 1 positive, if Cyclin D1 is negative then Mantle cell lymphoma will be SOX 11 positive .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is a characteristic feature of a pilocytic astrocytoma?", "options": [{"label": "A", "text": "Homer-wright rosettes", "correct": false}, {"label": "B", "text": "High cellularity", "correct": false}, {"label": "C", "text": "Rosenthal fibers", "correct": true}, {"label": "D", "text": "Necrosis", "correct": false}], "correct_answer": "C. Rosenthal fibers", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rosenthal fibers Pilocytic astrocytoma is a low-grade glioma that is commonly found in children and young adults. It is characterized by the presence of Rosenthal fibers, which are eosinophilic, elongated, and corkscrew-shaped structures.</p>\n<p><strong>Highyeild:</strong></p><p>Pilocytic Astrocytoma Low-grade astrocytoma Most common Primary brain tumor in children Site: Posterior fossa - cerebellum but may be supratentorial Histology: Astrocyte origin, GFAP + Bipolar neoplastic cells with hair-like projection Microcysts and Rosenthal fires present</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . Homer-wright rosettes: It is not a feature of pilocytic astrocytomas. These are pseudorosettes seen in medulloblastoma. Option: B. High cellularity: It is also not a feature of pilocytic astrocytomas. They have low cellularity and are composed of a mixture of piloid cells, Rosenthal fibers, and a loose fibrillar background. Option: D. Necrosis: It is not a feature of pilocytic astrocytomas. These tumors are typically non-necrotic and have a low propensity to invade surrounding tissues.</p>\n<p><strong>Table:</strong></p><p>Histological features of CNS tumors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of schwannoma except:", "options": [{"label": "A", "text": "Antoni A - spindle cells are arranged in intersecting fascicles", "correct": false}, {"label": "B", "text": "Antoni B- spindle cells separated by myxoid extracellular matrix and microcyst formation", "correct": false}, {"label": "C", "text": "Nucleus is wavy and buckled", "correct": false}, {"label": "D", "text": "Infiltrative pattern", "correct": true}], "correct_answer": "D. Infiltrative pattern", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Infiltrative pattern The infiltrative pattern is not a feature of schwannoma. Instead, schwannoma has a well-circumscribed border and tends to compress adjacent structures rather than infiltrate them.</p>\n<p><strong>Highyeild:</strong></p><p>Schwannomas Schwannoma is a benign nerve sheath tumor that arises from Schwann cells. Classically present at the cerebellopontine angle Benign tumor involving CNs V, VII, and VIII but can also be along peripheral nerve Origin: Schwann cells, S-100 + Histology: Antoni A pattern : Spindle cells are arranged in intersecting fascicles with nuclear palisading and Verocay bodies. Antoni B pattern: Spindle cells separated by myxoid extracellular matrix, microcyst formation, and fewer cellular areas. The nucleus is wavy and buckled : This is a characteristic feature of schwannoma and is known as Verocay bodies. Bilateral schwannomas are found in NF-2</p>\n<p><strong>Extraedge:</strong></p><p>Special features of schwannomas Roll over phenomenon Hitzelberger sign: Hypoesthesia of EAM posters-superiorly Most common presenting feature: Tinnitus Earliest ocular sign: loss of corneal reflex</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which immunohistochemistry shows positive expression in schwannoma?", "options": [{"label": "A", "text": "PanCK", "correct": false}, {"label": "B", "text": "EMA", "correct": false}, {"label": "C", "text": "S100", "correct": true}, {"label": "D", "text": "HMB45", "correct": false}], "correct_answer": "C. S100", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>S100 S100 is the immunohistochemical marker that shows positive expression in schwannoma. S100 is a calcium-binding protein found in neural crest-derived cells, including Schwann cells, and is used as a diagnostic marker for various tumors derived from these cells.</p>\n<p><strong>Highyeild:</strong></p><p>Schwannomas Schwannoma is a benign nerve sheath tumor that arises from Schwann cells. Classically present at the cerebellopontine angle Benign tumor involving CNs V, VII, and VIII but can also be along peripheral nerve Origin: Schwann cells, S-100 + Histology: Antoni A pattern : Spindle cells are arranged in intersecting fascicles with nuclear palisading and Verocay bodies. Antoni B pattern : Spindle cells separated by myxoid extracellular matrix, microcyst formation, and fewer cellular areas. The nucleus is wavy and buckled: This is a characteristic feature of schwannoma and is known as Verocay bodies. Bilateral schwannomas are found in NF-2</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. PanCK: it is used to detect cytokeratins, which are intermediate filaments found in epithelial cells and their tumors. Option: B. EMA: It (Epithelial Membrane Antigen) is a glycoprotein present in the cell membrane of epithelial cells and is used as a marker for various carcinomas. Option: D . HMB45: It is a marker for melanoma and other tumors of melanocytic origin.</p>\n<p><strong>Extraedge:</strong></p><p>Special features of schwannomas Roll over phenomenon Hitzelberger sign: Hypoesthesia of EAM posters-superiorly Most common presenting feature: Tinnitus Earliest ocular sign: loss of corneal reflex</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the most common primary malignant CNS tumor in children?", "options": [{"label": "A", "text": "Oligodendroglioma", "correct": false}, {"label": "B", "text": "Medulloblastoma", "correct": true}, {"label": "C", "text": "Pilocytic astrocytoma", "correct": false}, {"label": "D", "text": "Ependymoma", "correct": false}], "correct_answer": "B. Medulloblastoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Medulloblastoma Medulloblastoma is the most common primary malignant CNS tumor in children.</p>\n<p><strong>Highyeild:</strong></p><p>Medulloblastoma Most common malignant brain tumor in childhood It is a form of primitive neuroectodermal tumor Site: cerebellum Can compress 4th ventricle leading to non-communicating hydrocephalus Drop metastasis can occur in the spinal cord Histology: Homer-wright rosettes : Pseudorosettes with a central neuropil</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Oligodendroglioma: It is a primary brain tumor that typically occurs in adults and is characterized by cells that resemble oligodendrocytes. Option: C. Pilocytic astrocytoma: It is a low-grade primary brain tumor that occurs most commonly in children and adolescents. Option: D. Ependymoma: It is a primary brain tumor that arises from ependymal cells lining the ventricular system in the brain and spinal cord. It can occur in both children and adults but is more common in children.</p>\n<p><strong>Extraedge:</strong></p><p>Most common in Brain tumors: Most common primary CNS tumor: Glioma > meningioma Most common primary CNS tumor in children: Pilocytic astrocytoma Most common primary CNS tumor in adults: Astrocytoma Most common primary malignant tumor of the brain in children: Medulloblastoma Most common primary malignant tumor of the brain in adults: Glioblastoma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding Glioblastoma?", "options": [{"label": "A", "text": "It is a low-grade astrocytoma", "correct": false}, {"label": "B", "text": "It commonly occurs in children", "correct": false}, {"label": "C", "text": "It has a high recurrence rate after treatment", "correct": true}, {"label": "D", "text": "Whorls and Pseudorosettes on Histology", "correct": false}], "correct_answer": "C. It has a high recurrence rate after treatment", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It has a high recurrence rate after treatment Glioblastoma has a poor prognosis, with a high recurrence rate after treatment.</p>\n<p><strong>Highyeild:</strong></p><p>Glioblastoma Grade IV astrocytoma Common, highly malignant primary brain tumor Origin: Astrocyte, GFAP + Site: Cerebral hemispheres Can cross corpus callosum: Butterfly glioma Associated with EGFR amplification Histology: Pseudopalisading pleomorphic tumor cells which border central area of necrosis, hemorrhage, and/or microvascular proliferation Poor prognosis, with a high recurrence rate</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is a low-grade astrocytoma: It is not correct because glioblastoma is a high-grade astrocytoma. Option: B. It commonly occurs in children: It is not correct because glioblastoma is more commonly seen in adults, with a peak incidence in the sixth decade of life. Option: D. Whorls and Pseudorosettes on histology : These are characteristic of other types of brain tumors such as ependymoma and medulloblastoma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A histological section of an intracranial space-occupying lesion respected by a patient shows the findings given below. What is the likely diagnosis?", "options": [{"label": "A", "text": "Schwannoma", "correct": false}, {"label": "B", "text": "Oligodendroglioma", "correct": true}, {"label": "C", "text": "Neurofibroma", "correct": false}, {"label": "D", "text": "Neuroblastoma", "correct": false}], "correct_answer": "B. Oligodendroglioma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161663095-QTDP177006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Oligodendroglioma The given clinical scenario with histological findings of “ fried egg appearance ” suggests the diagnosis of Oligodendroglioma . The characteristic fried egg appearance refers to cells with round nuclei and clear cytoplasm that resemble fried eggs. This appearance is a hallmark of oligodendrogliomas.</p>\n<p><strong>Highyeild:</strong></p><p>Oligodendroglioma A relatively rare, slow-growing tumor Site: Most often in frontal lobes Age of onset: Fourth or fifth decade of life Often calcified Histology: Fried egg cells and chicken wire capillary pattern</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Schwannoma: Schwannomas typically show a spindle-shaped cell morphology and are positive for S100 immunostaining. Option: C. Neurofibroma: Neurofibromas consist of spindle cells with wavy nuclei arranged in a haphazard pattern and may have intermixed collagen and myxoid stroma. Option: D. Neuroblastoma: Neuroblastomas are typically seen in children and show neuroblastic cells with scant cytoplasm and hyperchromatic nuclei.</p>\n<p><strong>Extraedge:</strong></p><p>Mutations in Oligodendroglioma and their responsiveness to chemotherapy Mutations Chemo-radiation IDH 1, IDH 2 Sensitive 1p, 19q codeletion Sensitive 9p loss, 10q loss, CDKN2A mutation Resistant</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Triton tumor is a malignant peripheral nerve sheath tumor showing:", "options": [{"label": "A", "text": "Glandular differentiation", "correct": false}, {"label": "B", "text": "Cartilaginous differentiation", "correct": false}, {"label": "C", "text": "Rhabdomyoblastic differentiation", "correct": true}, {"label": "D", "text": "Osseous differentiation", "correct": false}], "correct_answer": "C. Rhabdomyoblastic differentiation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rhabdomyoblastic differentiation Triton tumor is a rare variant of malignant peripheral nerve sheath tumor (MPNST) that shows rhabdomyoblastic differentiation. Rhabdomyoblasts are skeletal muscle cells that are not typically seen in MPNST, but they are present in Triton tumors. The name \" Triton \" comes from the Greek mythological figure who was part man and part fish, reflecting the mixed differentiation seen in this tumor.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Glandular differentiation: It is not a feature seen in malignant peripheral nerve sheath tumors. These tumors arise from peripheral nerves and have a spindle cell morphology. Option: B. Cartilaginous differentiation: It is also not a feature seen in malignant peripheral nerve sheath tumors. These tumors are typically composed of spindle-shaped cells that resemble fibroblasts or Schwann cells. Option: D. Osseous differentiation: It is not typically seen in malignant peripheral nerve sheath tumors. These tumors can occasionally show areas of mineralization or calcification, but true bone formation is rare.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 68-year-old man presents with a 2-week history of tonic-clonic seizures that initially involve his left arm but have more recently progressed to involve his left leg. The cranial nerves are intact, and the Babinski sign is present. A CT scan reveals a mass in the left cerebral hemisphere. Histologic examination of the brain biopsy is shown in the image. Which of the following is the appropriate diagnosis?", "options": [{"label": "A", "text": "Craniopharyngioma", "correct": false}, {"label": "B", "text": "Ependymoma", "correct": false}, {"label": "C", "text": "Glioblastoma multiforme", "correct": true}, {"label": "D", "text": "Meningioma", "correct": false}], "correct_answer": "C. Glioblastoma multiforme", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161665596-QTDP177008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Glioblastoma multiforme The given clinical history with a histological image showing pseudo-palisading pleomorphic tumor cells suggests the diagnosis of Glioblastoma multiforme.</p>\n<p><strong>Highyeild:</strong></p><p>Glioblastoma Grade IV astrocytoma Common, highly malignant primary brain tumor Origin: Astrocyte, GFAP + Site: Cerebral hemispheres Can cross corpus callosum: Butterfly glioma Associated with EGFR amplification Histology: Pseudopalisading pleomorphic tumor cells which border central area of necrosis, hemorrhage and/or microvascular proliferation Poor prognosis, with a high recurrence rate</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Craniopharyngioma: This is a benign tumor that arises from embryonic remnants of Rathke's pouch. It is typically located in the sellar or suprasellar region and may cause symptoms such as visual field defects or endocrine dysfunction. The histology of craniopharyngioma shows characteristic calcifications and cysts. Option: B. Ependymoma: These are slow-growing tumors that arise from ependymal cells lining the ventricles or central canal of the spinal cord. They typically present with symptoms related to increased intracranial pressure, such as headaches and nausea. The histology of ependymoma shows perivascular pseudorosettes or true ependymal rosettes. Option:D. Meningioma: These are typically benign tumors that arise from the arachnoid cells covering the brain and spinal cord. They are most commonly located at the skull base or convexity of the brain and may cause symptoms such as seizures or focal neurological deficits. The histology of meningioma shows characteristic whorls of spindle cells.</p>\n<p><strong>Table:</strong></p><p>CNS Tumour Q. Most common CNS tumors? Secondaries (from lung > Breast) Q. Most common primary CNS tumors in adults? Meningioma Q. Most common primary CNS tumors in children ? Pilocytic Astrocytoma Q. Most common malignant primary CNS tumors in\n adults? Glioblastoma multiforme Q. Most common malignant primary CNS tumors in\n children ? Medulloblastoma Q. Most common CNS tumors in immunosuppressed\n individuals? Primary CNS Lymphoma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following factors leads to cellular ageing?", "options": [{"label": "A", "text": "Abnormal protein folding", "correct": false}, {"label": "B", "text": "Mutated DNA", "correct": false}, {"label": "C", "text": "Free radical injury", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Cellular ageing is the result of a progressive decline in cellular function and viability caused by genetic abnormalities and the accumulation of cellular and molecular damage due to the effects of exposure to exogenous influences. Factors leading to cellular ageing- Damaged DNA causes mutations. Damage of proteins causing misfolding of proteins. Plasma membrane damage is caused by phospholipid damage. Lipid peroxidation and injury by free radicals .</p>\n<p><strong>Highyeild:</strong></p><p>Telomere attrition in ageing: One mechanism of replicative senescence involves the progressive shortening of telomeres , which ultimately results in cell cycle arrest . When somatic cells replicate , a small section of the telomere is not duplicated and telomeres become progressively shortened . As the telomeres become shorter, the ends of chromosomes cannot be protected and are seen as broken DNA, which signals cell cycle arrest. Telomere length is maintained by nucleotide addition mediated by an enzyme called telomerase . Telomerase is RNA-dependant DNA polymerase which adds DNA to the 3’ end of the chromosome to avoid loss of genetic material with every duplication. They are present only in Eukaryotes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Abnormal protein folding. Correct . Option: B. Mutated DNA. Correct . Option: C. Free radical injury. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Telomerase activity is decreased in ageing and Progeria. Telomerase activity is increased in Cancer and progenitor cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is true regarding telomere?", "options": [{"label": "A", "text": "Short repeated sequence of DNA present at chromosome ends", "correct": false}, {"label": "B", "text": "With each replication, telomere length gets shortened", "correct": false}, {"label": "C", "text": "Shortening of telomeres is associated with ageing", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Telomeres are short repeated sequences of DNA present at the ends of linear chromosomes that are important for ensuring the complete replication of chromosome end s and for protecting the ends from fusion and degradation . When somatic cells replicate, a small section of the telomere is not duplicated and telomeres become progressively shortened . As the telomeres become shorter, the ends of chromosomes cannot be protected and are seen as broken DNA, which signals cell cycle arrest .</p>\n<p><strong>Highyeild:</strong></p><p>Telomere attrition in ageing: One mechanism of replicative senescence involves the progressive shortening of telomeres , which ultimately results in cell cycle arrest . When somatic cells replicate , a small section of the telomere is not duplicated and telomeres become progressively shortened . As the telomeres become shorter, the ends of chromosomes cannot be protected and are seen as broken DNA, which signals cell cycle arrest. Telomere length is maintained by nucleotide addition mediated by an enzyme called telomerase . Telomerase is RNA-dependant DNA polymerase which adds DNA to the 3’ end of the chromosome to avoid loss of genetic material with every duplication. They are present only in Eukaryotes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Short repeated sequence of DNA present at chromosome ends. Correct . Option: B. With each replication, telomere length gets shortened. Correct . Option: C. Shortening of telomeres is associated with ageing. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Telomerase activity is decreased in ageing and Progeria. Telomerase activity is increased in Cancer and progenitor cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the action of telomerase?", "options": [{"label": "A", "text": "It shortens the telomere length", "correct": false}, {"label": "B", "text": "It maintains the telomere length", "correct": true}, {"label": "C", "text": "It induces cellular ageing", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. It maintains the telomere length", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It maintains the telomere length Telomere length is maintained by nucleotide addition mediated by an enzyme called telomerase . Telomerase is a specialized RNA-protein complex that uses its own RNA as a template for adding nucleotides to the ends of chromosomes . Telomerase is expressed in germ cells and is present at low levels in stem cells , but it is absent in most somatic tissues .</p>\n<p><strong>Highyeild:</strong></p><p>Telomere attrition in ageing: One mechanism of replicative senescence involves the progressive shortening of telomeres , which ultimately results in cell cycle arrest . When somatic cells replicate , a small section of the telomere is not duplicated and telomeres become progressively shortened . As the telomeres become shorter, the ends of chromosomes cannot be protected and are seen as broken DNA, which signals cell cycle arrest. Telomere length is maintained by nucleotide addition mediated by an enzyme called telomerase . Telomerase is RNA-dependant DNA polymerase which adds DNA to the 3’ end of the chromosome to avoid loss of genetic material with every duplication. They are present only in Eukaryotes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It shortens the telomere length. Incorrect . Option: C. It induces cellular ageing. Incorrect . Option: D. All. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Telomerase activity is decreased in ageing and Progeria. Telomerase activity is increased in Cancer and progenitor cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In cancer cells, telomerase activity is-", "options": [{"label": "A", "text": "Increased", "correct": true}, {"label": "B", "text": "Decreased", "correct": false}, {"label": "C", "text": "Remains same", "correct": false}, {"label": "D", "text": "Variable", "correct": false}], "correct_answer": "A. Increased", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increased In immortalized cancer cells , telomerase is usually reactivated and telomere length is stabilized , allowing the cells to proliferate indefinitely.</p>\n<p><strong>Highyeild:</strong></p><p>Telomere attrition in ageing: One mechanism of replicative senescence involves the progressive shortening of telomeres , which ultimately results in cell cycle arrest . When somatic cells replicate , a small section of the telomere is not duplicated and telomeres become progressively shortened . As the telomeres become shorter, the ends of chromosomes cannot be protected and are seen as broken DNA, which signals cell cycle arrest. Telomere length is maintained by nucleotide addition mediated by an enzyme called telomerase . Telomerase is RNA-dependant DNA polymerase which adds DNA to the 3’ end of the chromosome to avoid loss of genetic material with every duplication. They are present only in Eukaryotes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Decreased. Incorrect . Option: C. Remains same. Incorrect . Option: D. Variable. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Telomerase activity is decreased in ageing and Progeria. Telomerase activity is increased in Cancer and progenitor cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are ways of delaying ageing except?", "options": [{"label": "A", "text": "Decrease intake of glucose", "correct": false}, {"label": "B", "text": "More Sirtuins", "correct": false}, {"label": "C", "text": "Decrease calories", "correct": false}, {"label": "D", "text": "None of the above", "correct": true}], "correct_answer": "D. None of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above Glucose intake causes more IGF-1 signals which cause more replication which leads to telomere shortening . It causes ageing . So decrease in glucose and calories cause a delay in ageing . Sirtuins are a family of NAD-dependent protein deacetylases . Sirtuins are thought to promote the expression of several genes whose products increase longevity . These include proteins that inhibit metabolic activity, reduce apoptosis, stimulate protein folding, and counteract the harmful effects of oxygen free radicals . Sirtuins also increase insulin sensitivity and glucose metabolism and may be targeted for the treatment of diabetes .</p>\n<p><strong>Highyeild:</strong></p><p>Sirtuins Sirtuins are a family of NAD-dependent protein deacetylases . There are at least seven types of sirtuins in mammals. Sirtuins are thought to promote the expression of several genes whose products increase longevity . These include proteins that: Inhibit metabolic activity Reduce apoptosis Stimulate protein folding Counteract the harmful effects of oxygen-free radicals .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Decrease intake of glucose. Causes delay in ageing . Option: B. More Sirtuins. Causes delay in ageing . Option: C. Decrease calories. Causes delay in ageing .</p>\n<p><strong>Extraedge:</strong></p><p>Sirtuins also increase insulin sensitivity and glucose metabolism and may be targeted for the treatment of diabetes . The level of Sirtuins can be increased by: Caloric restriction . A constituent of red wine may activate sirtuins.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What are the functions of Sirtuins?", "options": [{"label": "A", "text": "Decrease cell metabolism and apoptosis", "correct": false}, {"label": "B", "text": "Increase cell repair", "correct": false}, {"label": "C", "text": "Maintains telomere length", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Sirtuins are thought to promote the expression of several genes whose products increase longevity . These include proteins that inhibit metabolic activity, reduce apoptosis, stimulate protein folding, and counteract the harmful effects of oxygen free radicals . Sirtuins also increase insulin sensitivity and glucose metabolism and may be targeted for the treatment of diabetes .</p>\n<p><strong>Highyeild:</strong></p><p>Sirtuins Sirtuins are a family of NAD-dependent protein deacetylases . There are at least seven types of sirtuins in mammals. Sirtuins are thought to promote the expression of several genes whose products increase longevity . These include proteins that: Inhibit metabolic activity Reduce apoptosis Stimulate protein folding Counteract the harmful effects of oxygen-free radicals .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Decrease cell metabolism and apoptosis. Correct . Option: B. Increase cell repair. Correct . Option: C. Maintains telomere length. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Sirtuins also increase insulin sensitivity and glucose metabolism and may be targeted for the treatment of diabetes . The level of Sirtuins can be increased by: Caloric restriction . A constituent of red wine may activate sirtuins.</p>\n<p><strong>Table:</strong></p><p>Sirtuins Sirtuins are a family of NAD-dependent protein deacetylases . There are at least seven types of sirtuins in mammals. Sirtuins are thought to promote the\n expression of several genes whose products increase longevity . These include proteins that: Inhibit metabolic activity Reduce apoptosis Stimulate protein folding Counteract the harmful effects of oxygen - free radicals Sirtuins also increase insulin sensitivity\n and glucose metabolism and may be targeted for the treatment of diabetes . The level of Sirtuins can be increased by: 1. Caloric restriction . 2. A constituent of red wine may activate\nsirtuins.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding Werner syndrome ?", "options": [{"label": "A", "text": "Premature ageing, defect in telomerase", "correct": false}, {"label": "B", "text": "Premature ageing, defect in DNA helicase", "correct": true}, {"label": "C", "text": "Delayed ageing, defect in DNA replicase", "correct": false}, {"label": "D", "text": "Delayed ageing, increase telomerase activity", "correct": false}], "correct_answer": "B. Premature ageing, defect in DNA helicase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Premature ageing, defect in DNA helicase Patients with Werner syndrome show premature ageing , and the defective gene product is a DNA helicase , a protein involved in DNA replication and repair and other functions requiring DNA unwinding. A defect in this enzyme causes rapid accumulation of chromosomal damage that may mimic some aspects of the injury that normally accumulates during cellular ageing .</p>\n<p><strong>Highyeild:</strong></p><p>Also known as \" adult progeria \" is a rare, autosomal recessive ( AR ) disorder. Premature ageing in Wer N er syndrome is d/t defect in D N A helicase.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Premature ageing, defect in telomerase. Incorrect . Option: C. Delayed ageing, defect in DNA replicase. Incorrect . Option: D. Delayed ageing, increase telomerase activity. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Bloom syndrome also shows defects in DNA helicase NOTE: Do not confuse with Wer M er syndrome which is seen in M EN-1.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "After binding of complement and antibody on the surface of encapsulated bacteria, the process of phagocytosis by polymorphonuclear leukocytes/macrophages is enhanced by all of the following opsonins, except?", "options": [{"label": "A", "text": "C3b complement protein", "correct": false}, {"label": "B", "text": "IgG antibody", "correct": false}, {"label": "C", "text": "Mannose-binding Lectin (MBL)", "correct": false}, {"label": "D", "text": "CD11b/CD18", "correct": true}], "correct_answer": "D. CD11b/CD18", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD11b/CD18 CD11b/CD18 (MAC-1) is macrophage integrin which helps in the binding of microbes to macrophages and is not opsonins . Phagocytosis involves sequential steps: Recognition and attachment of the particle to be ingested by the leukocyte Opsonization refers to the coating of an antigen to increase the efficiency of phagocytosis. Engulfment with subsequent formation of a phagocytic vacuole The killing of the microbe and degradation of the ingested material. The efficiency of phagocytosis is greatly enhanced when microbes are coated with opsonins for which the phagocytes express high-affinity receptors. The major opsonins are: IgM and Fc receptors of IgG C3b breakdown product of complement ( C3a, C 4b, C5b ) Mannose-binding lectin Fibrinogen C- Reactive Protein ( CRP )</p>\n<p><strong>Highyeild:</strong></p><p>Neutrophil extracellular traps (NETs) Neutrophil extracellular traps are extracellular fibrillar networks that concentrate antimicrobial substances at sites of infection and trap microbes, helping to prevent their spread. They are produced by neutrophils in response to infectious pathogens ( mainly bacteria and fungi ) and inflammatory mediators (e.g., chemokines, cytokines [mainly interferons], complement proteins, and ROS ). The extracellular traps consist of a viscous meshwork of nuclear chromatin that binds and concentrates granule proteins such as antimicrobial peptides and enzymes. In this process, the nuclei of the neutrophils are lost, leading to the death of the cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. C3b complement protein. Opsonin . Option: B. IgG antibody. Opsonin . Option: C. Mannose-binding Lectin (MBL). Opsonin .</p>\n<p><strong>Extraedge:</strong></p><p>The nuclear chromatin in the NETs , which includes histones and associated DNA, has been postulated to be a source of nuclear antigens in systemic autoimmune diseases , particularly lupus , in which individuals react against their own DNA and nucleoproteins. Neutrophil extracellular traps (NETS). (A) Healthy neutrophils with nuclei stained red and cytoplasm stained green. (B) Release of nuclear material from neutrophils (note that two have lost their nuclei), forming extracellular traps. (C) Electron micrograph of bacteria (staphylococci) trapped in NETS. (From Brinkmann V, Zychlinsky A: Beneficial suicide: why neutrophils die to make NETS, Nat Rev Microbiol 5:577, 2007, with permission.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is associated with chronic bronchitis?", "options": [{"label": "A", "text": "Decreased mucus production", "correct": false}, {"label": "B", "text": "Increased FEV1/FVC ratio", "correct": false}, {"label": "C", "text": "The patients are called blue bloaters", "correct": true}, {"label": "D", "text": "Associated with alpha-1 antitrypsin deficiency", "correct": false}], "correct_answer": "C. The patients are called blue bloaters", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The patients are called blue bloaters Patients with chronic bronchitis are often referred to as blue bloaters due to the bluish discoloration(Cyanosis) of their skin from hypoxia and the associated peripheral edema.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic bronchitis It is a type of chronic obstructive pulmonary disease (COPD) characterized by chronic cough and sputum production. Cause: Chronic irritation of the airways, most commonly from cigarette smoke, air pollution, or occupational exposure to dust or chemicals. Histopathological features: Mild chronic inflammation of the airways, predominantly composed of lymphocytes and plasma cells. Enlargement of the mucus-secreting glands in the trachea and bronchi. Hyperplasia and hypertrophy of the goblet cells in the bronchial epithelium lead to increased mucus production and secretion. Thickening of the bronchial walls due to fibrosis (formation of scar tissue) and smooth muscle hypertrophy leading to narrowing of the airways. In severe cases, metaplasia of the bronchial epithelium may occur , with squamous cell metaplasia being the most common type. Features : Chronic cough and sputum production for at least three months in each of two consecutive years Absence of any other known causes of cough Spirometry showing evidence of airflow obstruction, indicated by an FEV1/FVC ratio less than 0.7 after bronchodilator administration Other symptoms: Dyspnea, wheezing, and chest tightness .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Decreased mucus production: It is incorrect because chronic bronchitis is characterized by hypersecretion of mucus, not decreased mucus production. Option: B. Increased FEV1/FVC ratio: It is also incorrect because the FEV1/FVC ratio is typically decreased in chronic bronchitis due to the airflow obstruction caused by the chronic inflammation of the airways. Option: D. Associated with alpha-1 antitrypsin deficiency: It is associated with emphysema and not chronic bronchitis.</p>\n<p><strong>Extraedge:</strong></p><p>Emphysema Vs Chronic Bronchitis Emphysema Chronic Bronchitis Aka Pink puffers Blue bloaters Presentation Shortness of breath and scanty sputum production Chronic productive cough General Appearance Thin, sometimes cachexic, with rosy skin tones Often overweight, obese Sputum Scanty , Mucoid Copious , Purulent Cor Pulomonale Rare, except in the late stages More prominent Chest X-ray findings Hyperinflated lungs , small heart. Diaphragm: low and flat Normal-sized lungs, Right ventricular hypertrophy. Normal shaped diaphragm Other findings Barrel chest Cyanotic, Peripheral edema Pulmonary function tests Decreased FEV1/FVC ratio, decreased DLCO , increased residual volume Decreased FEV1/FVC ratio, normal or slightly decreased DLCO, normal or increased residual volume</p>\n<p><strong>Table:</strong></p><p>It is a histopathologic measurement used to assess the degree of\n hypertrophy of the mucus-secreting glands in the trachea and bronchi in\n chronic bronchitis . It is calculated by dividing the thickness of the submucosal gland\n layer by the thickness of the bronchial wall between the basement membrane\n and the cartilage. A Reid's index\n greater than 0.4 is considered indicative of chronic bronchitis , while\n values less than 0.4 are considered normal.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old man presents to the clinic with a persistent cough and sputum production for the past three months. He has a history of smoking for over 30 years and has been diagnosed with COPD. On physical examination, he has wheezing and crackles on auscultation. Which of the following is not true regarding the histopathology of the diagnosis?", "options": [{"label": "A", "text": "Hyperemia, swelling, and edema of the mucous membranes", "correct": false}, {"label": "B", "text": "Chronic inflammation of airways predominantly with lymphocytes", "correct": false}, {"label": "C", "text": "Depleted mucus-secreting glands of trachea and bronchi", "correct": true}, {"label": "D", "text": "Metaplasia of the bronchial epithelium", "correct": false}], "correct_answer": "C. Depleted mucus-secreting glands of trachea and bronchi", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Depleted mucus-secreting glands of trachea and bronchi The given clinical scenario is suggestive of Chronic bronchitis. Enlargement of the mucus-secreting glands in the trachea and bronchi is a characteristic feature, not depleted glands .</p>\n<p><strong>Highyeild:</strong></p><p>Chronic bronchitis It is a type of chronic obstructive pulmonary disease (COPD) characterized by chronic cough and sputum production. Cause: Chronic irritation of the airways, most commonly from cigarette smoke, air pollution, or occupational exposure to dust or chemicals. Histopathological features: Mild chronic inflammation of the airways, predominantly composed of lymphocytes and plasma cells. Enlargement of the mucus-secreting glands in the trachea and bronchi. Hyperplasia and hypertrophy of the goblet cells in the bronchial epithelium lead to increased mucus production and secretion. Thickening of the bronchial walls due to fibrosis (formation of scar tissue) and smooth muscle hypertrophy leading to narrowing of the airways. In severe cases, metaplasia of the bronchial epithelium may occur , with squamous cell metaplasia being the most common type. Features : Chronic cough and sputum production for at least three months in each of two consecutive years Absence of any other known causes of cough Spirometry showing evidence of airflow obstruction, indicated by an FEV1/FVC ratio less than 0.7 after bronchodilator administration Other symptoms: Dyspnea, wheezing, and chest tightness .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., D: All of the above statements are true.</p>\n<p><strong>Extraedge:</strong></p><p>Emphysema Vs Chronic Bronchitis Emphysema Chronic Bronchitis Aka Pink puffers Blue bloaters Presentation Shortness of breath and scanty sputum production Chronic productive cough General Appearance Thin, sometimes cachexic, with rosy skin tones Often overweight, obese Sputum Scanty , Mucoid Copious , Purulent Cor Pulomonale Rare, except in the late stages More prominent Chest X-ray findings Hyperinflated lungs , small heart. Diaphragm: low and flat Normal-sized lungs, Right ventricular hypertrophy. Normal shaped diaphragm Other findings Barrel chest Cyanotic, Peripheral edema Pulmonary function tests Decreased FEV1/FVC ratio, decreased DLCO , increased residual volume Decreased FEV1/FVC ratio, normal or slightly decreased DLCO, normal or increased residual volume</p>\n<p><strong>Table:</strong></p><p>It is a histopathologic measurement used to assess the degree of hypertrophy of the mucus-secreting glands in the trachea and bronchi in chronic bronchitis . It is calculated by dividing the thickness of the submucosal gland layer by the thickness of the bronchial wall between the basement membrane and the cartilage. A Reid's index greater than 0.4 is considered indicative of chronic bronchitis , while values less than 0.4 are considered normal.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which one of the following statements is correct regarding chronic granulomatous disease-", "options": [{"label": "A", "text": "It is an autosomal dominant disease", "correct": false}, {"label": "B", "text": "It is characterised by abnormal bacterial phagocytosis", "correct": false}, {"label": "C", "text": "Recurrent streptococcal infections are usual in this disease", "correct": false}, {"label": "D", "text": "Nitroblue-tetrazolium test is helpful for screening", "correct": true}], "correct_answer": "D. Nitroblue-tetrazolium test is helpful for screening", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nitroblue-tetrazolium test is helpful for screening</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Granulomatous Disease Inherited defects in microbicidal activity . The importance of oxygen-dependent bactericidal mechanisms is shown by the existence of a group of congenital disorders called chronic granulomatous disease , which are characterised by defects in bacterial killing and render patients susceptible to recurrent bacterial infection . Chronic granulomatous disease results from inherited defects in the genes encoding components of phagocyte oxidase (PHOX gene) , the phagolysosomal enzyme that generates superoxide (O 2•), causing a defective Respiratory burst . The most common variants are an X-linked defect in one of the membrane-bound components ( gp91phox ) and autosomal recessive defects in the genes encoding two cytoplasmic components ( p47phox and p67phox ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is an autosomal dominant disease. The most common variants are X-linked defects . Option: B. It is characterised by abnormal bacterial phagocytosis. Characterised by defective Respiratory burst . Option: C. Recurrent streptococcal infections are usual in this disease. Increases susceptibility to infections with aureus, some gram-negative bacteria, and fungi .</p>\n<p><strong>Extraedge:</strong></p><p>The name of this disease comes from the macrophage-rich chronic inflammatory reaction that tries to control the infection when the initial neutrophil defence is inadequate. This often leads to c tions of activated macrophages that wall off the microbes, forming granulomas. The Nitroblue tetrazolium test is helpful for screening . Defects in neutrophil function , as in chronic granulomatous disease, increase susceptibility to infections with aureus, some gram-negative bacteria, and fungi .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25-year-old male presented with fever and malaise for the last 15 days. A 2x2cm cervical node was palpable, the biopsy of which has been shown below. Identify the lesion?", "options": [{"label": "A", "text": "Metastasis", "correct": false}, {"label": "B", "text": "Sarcoidosis", "correct": false}, {"label": "C", "text": "Squamous cell ca", "correct": false}, {"label": "D", "text": "Tubercular granuloma", "correct": true}], "correct_answer": "D. Tubercular granuloma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686816436974-QTDP023002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tubercular granuloma History is classical of TB: young adult, with fever, malaise, cervical LN .</p>\n<p><strong>Highyeild:</strong></p><p>In the usual hematoxylin and eosin preparations, the activated macrophages in granulomas have pink granular cytoplasm with indistinct cell boundaries. They are called epithelioid cells because they resemble epithelia. A collar of lymphocytes surrounds the aggregates of epithelioid macrophages. Older granulomas may have a rim of fibroblasts and connective tissue . Frequently, but not invariably, multinucleated giant cells 40 to 50 µm in diameter are found in granulomas called Langhans giant cells . They consist of a large mass of cytoplasm and many nuclei , and they derive from the fusion of multiple activated macrophages. In granulomas associated with certain infectious organisms (most classically Mycobacterium tuberculosis ), a combination of hypoxia and free radical-mediated injury leads to a central zone of necrosis . Grossly , this has a granular, cheesy appearance and is therefore called caseous necrosis . Microscopically , this necrotic material appears as amorphous, structureless, eosinophilic, granular debris with a complete loss of cellular details .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. History not suggestive of malignancy. Option: B. History not suggestive of sarcoidosis. Option: C. Squamous cell ca. History not suggestive of SCC. Histology of SCC shows squamous cells with keratin pearls .</p>\n<p><strong>Extraedge:</strong></p><p>Typical tuberculous granuloma showing an area of central necrosis surrounded by multiple Langhans-type giant cells, epithelioid cells, and lymphocytes. The granulomas in Crohn's disease, sarcoidosis, and foreign body reactions tend NOT to have necrotic centres and are said to be noncaseating . The healing of granulomas is accompanied by fibrosis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Stellate granuloma is seen in:", "options": [{"label": "A", "text": "Sarcoidosis", "correct": false}, {"label": "B", "text": "Cat-scratch disease", "correct": true}, {"label": "C", "text": "Cryptococcosis", "correct": false}, {"label": "D", "text": "Histoplasmosis", "correct": false}], "correct_answer": "B. Cat-scratch disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cat-scratch disease Stellate granuloma is seen in Cat-scratch disease .</p>\n<p><strong>Highyeild:</strong></p><p>Cat-scratch disease: Bacterial infection caused by Bartonella henselae . Acquired infected cat/kitten scratch Histology Characterised by granulomatous inflammation of lymph node s Skin lesion demonstrates a circumscribed focus of necrosis . Regional lymph nodes demonstrate follicular hyperplasia with central stellate necrosis with neutrophils, surrounded by palisading histiocytes (suppurative granulomas) and sinuses packed with monocytoid B cells, usually without perifollicular and intrafollicular epithelioid cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Sarcoidosis. Non Caseating granuloma. Option: C. Cryptococcosis. Non Caseating granuloma. Option: D. Histoplasmosis. Caseating granuloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following statements is true -", "options": [{"label": "A", "text": "Peak incidence of Chronic myeloid leukaemia is in the fifth to sixth decades of life", "correct": true}, {"label": "B", "text": "Hairy cell leukaemia in more than 50 years has a good prognosis", "correct": false}, {"label": "C", "text": "Acute lymphoid leukaemia in less than 1 year has a good prognosis", "correct": false}, {"label": "D", "text": "Chronic lymphocytic leukaemia occurs in less than 50 years of age", "correct": false}], "correct_answer": "A. Peak incidence of Chronic myeloid leukaemia is in the fifth to sixth decades of life", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Peak incidence of Chronic myeloid leukaemia is in the fifth to sixth decades of life Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score .</p>\n<p><strong>Highyeild:</strong></p><p>The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Hairy cell leukaemia in more than 50 years has a good prognosis. False, Prognosis is worse for those > 50 years and those with Hb level < 10 g/dL and white cell counts < 2 x 10^9/L . Option: C. Acute lymphoid leukaemia in less than 1 year has a good prognosis. False, ALL in children < 1 year and > 10 years have a poor prognosis . Option: D. Chronic lymphocytic leukaemia occurs in less than 50 years of age. False, median age at diagnosis of CLL is 60 years and there is a 2:1 male predominance .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Best investigation for BCR-ABL:", "options": [{"label": "A", "text": "Flow cytometry", "correct": false}, {"label": "B", "text": "Fluorescent in situ hybridization", "correct": true}, {"label": "C", "text": "ELISA", "correct": false}, {"label": "D", "text": "Polymerase chain reaction", "correct": false}], "correct_answer": "B. Fluorescent in situ hybridization", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fluorescent in situ hybridization Most in situ hybridization procedures use fluorescent probes to detect DNA sequences , and the process is commonly referred to as FISH (fluorescence in situ hybridization). FISH and other in situ hybridization procedures are important in the clinical diagnosis of various chromosomal abnormalities, including deletions, duplications, and translocations . Either karyotyping and FISH or qualitative RT-PCR can be used for the diagnosis of CML. However, FISH is preferred due to its optimal sensitivity and ability to detect variants.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance other the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Flow cytometry. Used for Immunophenotyping e. can tell CD markers but not translocations. Option: C. ELISA stands for enzyme-linked immunoassay. It is a commonly used laboratory test to detect antibodies in the blood . Option: D. Polymerase chain reaction. Can be used to detect BCR-ABL fusion but it is best done by FISH .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In patients with Chronic Myeloid Leukaemia", "options": [{"label": "A", "text": "ABL gene on Chr 22 is translocated to the BCR gene on Chr 9", "correct": false}, {"label": "B", "text": "The fusion gene BCR-ABL forms a protein with tyrosine kinase activity", "correct": true}, {"label": "C", "text": "Splenomegaly is unusual", "correct": false}, {"label": "D", "text": "Philadelphia chromosome-positive patients respond poorly to Imatinib", "correct": false}], "correct_answer": "B. The fusion gene BCR-ABL forms a protein with tyrosine kinase activity", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The fusion gene BCR-ABL forms a protein with tyrosine kinase activity</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College Girl appearance/ Garden Party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. ABL gene on Chr 22 is translocated to the BCR gene on Chr 9. False, as the ABL gene is on Chr 9q while BCR is on Chr 22q . Option: C. Splenomegaly is unusual. False, Massive splenomegaly is a feature of CML . Option: D. Philadelphia chromosome-positive patients respond poorly to Imatinib. False, as a response to Imatinib is good in patients with Philadelphia chromosome +ve .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "About CML in children true is:", "options": [{"label": "A", "text": "Translocation between the long arm of chr 9 and the short arm of chr 22", "correct": false}, {"label": "B", "text": "Protein tyrosine kinase inhibitors are the drug of choice", "correct": true}, {"label": "C", "text": "Most commonly presents in a blast crisis", "correct": false}, {"label": "D", "text": "2nd most common malignancy", "correct": false}], "correct_answer": "B. Protein tyrosine kinase inhibitors are the drug of choice", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Protein tyrosine kinase inhibitors are the drug of choice True, Imatinib , a tyrosine kinase inhibitor, is the drug of choice.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Translocation between the long arm of chr 9 and the short arm of chr 22. False , as translocation is between long arms of chr 9 & 22 . Option: C. Most commonly presents in a blast crisis. False , most commonly present in the chronic phase . Option: D. 2nd most common malignancy. False , the commonest tumour in children is ALL , followed by CNS tumours .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A peripheral smear with increased neutrophils, basophils, eosinophils, and platelets is highly suggestive of -", "options": [{"label": "A", "text": "Acute myeloid leukaemia", "correct": false}, {"label": "B", "text": "Acute lymphoblastic leukaemia", "correct": false}, {"label": "C", "text": "Chronic myelogenous leukaemia", "correct": true}, {"label": "D", "text": "Myelodysplastic syndrome", "correct": false}], "correct_answer": "C. Chronic myelogenous leukaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic myelogenous leukaemia A peripheral smear with increased neutrophils, basophils, eosinophils, and platelets is highly suggestive of CML.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukaemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Acute myeloid leukaemia. False, diagnosis of AML is based on the presence of at least 20% myeloid blasts in the bone marrow . Option: B. Acute lymphoblastic leukaemia. False, diagnosis of ALL is based on the presence of at least 20% lymphoid blasts in the bone marrow . Option: D. Myelodysplastic syndrome. MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Characteristic features of CML?", "options": [{"label": "A", "text": "Auer rods", "correct": false}, {"label": "B", "text": "Basophilia", "correct": true}, {"label": "C", "text": "Increased LAP score", "correct": false}, {"label": "D", "text": "Bone marrow fibrosis", "correct": false}], "correct_answer": "B. Basophilia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Basophilia Characteristic features of CML are Basophilia & Philadelphia Chromosome t(9;22) .</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in the leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Auer rods. False, Auer rods are characteristic of Myeloblasts . Option: C. Increased LAP score. False, Low LAP score is seen in CML . Option: D. Bone marrow fibrosis. The marrow is markedly hypercellular because of massively increased numbers of maturing granulocytic precursors.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old man presented with fatigue, weight loss and heaviness in the left hypochondrium for 6 months. The hemogram showed Hb = 10gm/dL, TLC 5 lakhs/mm3, platelet counts 4 lakhs/mm3, DLC neutrophil 55 %, lymphocytes 4 %, monocytes 2 %, basophils 6%, metamyelocytes 10%, myelocytes 18%, promyelocytes 2% and blasts 3%. The most likely cytogenetic abnormality, in this case, is:", "options": [{"label": "A", "text": "t (1;21)", "correct": false}, {"label": "B", "text": "t (9;22)", "correct": true}, {"label": "C", "text": "t (15;17)", "correct": false}, {"label": "D", "text": "Trisomy 21", "correct": false}], "correct_answer": "B. t (9;22)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>t (9;22) This is an old-aged patient presenting with splenomegaly (heaviness in left hypochondrium) and anaemia (easy fatigability). Blood picture shows Leukocytosis with Basophilia and Myeloid series (metamyelocytes 10%, myelocytes 18%, promyelocytes 2% and blasts 3%), suggestive of CML . The Cytogenetic abnormality seen in CML is t (9; 22)</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloid Leukaemia: Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . CML will have all cells in the lineage present in the peripheral smear. However, leukocytosis with a shift to the left is not diagnostic of CML as it can be seen in leukemoid reaction too. These are differentiated on the basis of LAP score , with CML showing a low LAP score and Leukamoid reaction showing a high LAP score . The diagnostic hallmark of CML : t (9;22) Philadelphia chromosome (detected by Cytogenetics/ karyotyping ) with fusion transcript BCR-ABL (detected by PCR ). Bone marrow examination: Hypercellular marrow with a predominance of the myeloid lineage, this appearance is called College girl appearance/ Garden party appearance . Bone marrow smear with 12% blasts (not shown here), neutrophils at all stages of maturation Treatment: Tyrosine kinase inhibitors (Imatinib) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. t (1;21). Incorrect . Option: C. t (15;17). Incorrect . Option: D. Trisomy 21. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The dilated endoplasmic reticulum is called?", "options": [{"label": "A", "text": "Asteroid bodies", "correct": false}, {"label": "B", "text": "Auer bodies", "correct": false}, {"label": "C", "text": "Birbeck bodies", "correct": false}, {"label": "D", "text": "Dohle bodies", "correct": true}], "correct_answer": "D. Dohle bodies", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dohle bodies In sepsis or severe inflammatory disorders (e.g., Kawasaki disease), leukocytosis can have morphologic changes in the neutrophils : Cytoplasmic vacuoles Toxic granules, which are coarser and darker than the normal neutrophilic granules, represent abnormal azurophilic (primary) granules. Döhle bodies are patches of the dilated endoplasmic reticulum that appear as sky-blue cytoplasmic “puddles” Döhle bodies are seen in Myelodysplastic syndromes Sepsis Chediak Higashi syndrome Reactive changes in neutrophils. Neutrophils containing coarse purple cytoplasmic granules (toxic granulations) and blue cytoplasmic patches of dilated endoplasmic reticulum (Döhle bodies) (arrow) are observed in this peripheral blood smear prepared from a patient with bacterial sepsis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Asteroid bodies. Asteroid bodies : stellate/ star-shaped inclusions in giant cells seen in Sarcoidosis . Option: B. Auer bodies. Cytoplasmic rod-shaped structures are found in immature myeloid cells (known as faggot cells ). The bodies occur in acute myeloid leukaemia (M3) and are thought to be abnormal lysosomes. They contain the enzymes peroxidase and acid phosphatase and stain red with azure eosin. Can activate the coagulation pathway and can initiate DIC . Option: C. Birbeck bodies. These granules are shaped like rods or tennis rackets with a central linear density and a striated appearance. They are characteristic of Langerhans cell histiocytosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The mutation is seen in systemic mastocytosis:", "options": [{"label": "A", "text": "FGFR1 fusion genes", "correct": false}, {"label": "B", "text": "BCR-ABL fusion gene", "correct": false}, {"label": "C", "text": "JAK 2-point mutation", "correct": false}, {"label": "D", "text": "c-kit point mutation", "correct": true}], "correct_answer": "D. c-kit point mutation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>c-kit point mutation The mutation commonly seen in systemic mastocytosis is a c-kit point mutation . The c-kit gene codes for a receptor tyrosine kinase that is expressed on the surface of mast cells . In systemic mastocytosis , there is a mutation in the c-kit gene that leads to the constitutive activation of the c-kit receptor , resulting in the abnormal proliferation and accumulation of mast cells in various tissues. Mutations in other genes, such as FGFR1, BCR-ABL, and JAK2, are associated with other myeloproliferative neoplasms but are not commonly associated with systemic mastocytosis.</p>\n<p><strong>Highyeild:</strong></p><p>Mutations associated with Myeloproliferative disorders: Disorder Mutation Chronic myeloid leukemia BCR-ABL fusion gene Polycythemia vera JAK2 mutations Essential thrombocythemia JAK2 mutations CALR mutations MPL mutations Primary myelofibrosis JAK2 mutations CALR mutations MPL mutations Systemic mastocytosis KIT mutations Chronic eosinophilic leukemia FIPILI-PDGFRA fusion gene PDE4DIP-PDGFRB fusion gene Myeloid/lymphoid neoplasms with eosinophilia and tyrosine kinase gene mutationsb Various fusion genes involving FGFRI, PDGFRA, PDGFRB, or JAK2</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. FGFR 1 fusion gene. FGFR1 fusion genes are seen in some cases of 8p11 myeloproliferative syndrome . Option: B. BCR-ABL fusion gene. BCR-ABL fusion gene is seen in Chronic Myeloid Leukaemia . Option: C. JAK 2-point mutation. JAK2 point mutations are seen in Polycythemia Vera, Essential Thrombocythemia, and Primary Myelofibrosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a chronic myeloproliferative disorder?", "options": [{"label": "A", "text": "Polycythemia vera", "correct": false}, {"label": "B", "text": "Myeloid metaplasia", "correct": false}, {"label": "C", "text": "CML", "correct": false}, {"label": "D", "text": "Essential thrombocytopenia", "correct": true}], "correct_answer": "D. Essential thrombocytopenia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Essential thrombocytopenia Myeloid metaplasia is another name for myelofibrosis . Essential ThromboCYTOSIS is Chronic Myeloproliferative Disorder (not thrombocytopenia)</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Myeloproliferative Disorders: The common pathogenic feature of myeloproliferative neoplasms is the presence of mutated, constitutively activated tyrosine kinases or other acquired aberrations in signalling pathways that lead to growth factor independence . Chronic Myeloid Leukaemia Chronic Neutrophilic Leukaemia Chronic Eosinophilic Leukaemia Polycythemia Vera Essential Thrombocytosis Primary Myelofibrosis There is a considerable degree of clinical and morphologic overlap among myeloproliferative neoplasms. The common features include: Increased proliferative drive in the bone marrow Homing of the neoplastic stem cells to secondary hematopoietic organs, producing extramedullary hematopoiesis Variable transformation to a spent phase characterized by marrow fibrosis and peripheral blood cytopenias Variable transformation to acute leukaemia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Polycythemia vera. Correct . Option: B. Myeloid metaplasia. Correct . Option: C. CML. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following are histological features of chronic pancreatitis in the pancreas?", "options": [{"label": "A", "text": "Fibrosis", "correct": false}, {"label": "B", "text": "Atrophy and dropout acini", "correct": false}, {"label": "C", "text": "Dilation pancreatic duct", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Chronic pancreatitis is a long-term inflammation of the pancreas that results in progressive damage and structural changes. Histologically, chronic pancreatitis exhibits multiple characteristic features, including fibrosis, atrophy and dropout of acini, and dilation of the pancreatic duct. Hence, option D. All of the above is correct.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic pancreatitis It is characterized by progressive inflammation and fibrosis of the pancreas , leading to permanent damage and functional impairment. The histological features of chronic pancreatitis typically include: Fibrosis : The pancreas shows significant fibrosis, which is the deposition of extracellular matrix proteins that can lead to scarring and loss of function. Atrophy and dropout of acin i: The acini, which are the functional units of the pancreas responsible for producing digestive enzymes, become atrophic and may drop out over time, leading to further loss of function. Dilation of pancreatic duct : The pancreatic duct may become dilated and distorted as a result of chronic inflammation and fibrosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Fibrosis: It refers to the excessive accumulation of fibrous connective tissue. In chronic pancreatitis, ongoing inflammation and tissue damage lead to the deposition of fibrous tissue, resulting in the replacement of healthy pancreatic tissue. Fibrosis is a hallmark feature of chronic pancreatitis. Option:B. Atrophy and dropout of acini: Acini are the functional units of the pancreas responsible for producing digestive enzymes. In chronic pancreatitis, there is progressive destruction of acini, leading to their atrophy and dropout. This loss of acinar cells contributes to the impaired exocrine function of the pancreas in chronic pancreatitis. Option:C. Dilation of the pancreatic duct: Chronic inflammation and fibrosis can cause narrowing and scarring of the pancreatic duct, leading to obstruction. This obstruction results in dilation (enlargement) of the pancreatic duct. Dilation of the pancreatic duct can be observed histologically in chronic pancreatitis.</p>\n<p><strong>Table:</strong></p><p>Cystic\n neoplasms of the pancreas Characteristics Serous cystadenoma Mucinous cystadenoma Intraductal papillary mucinous neoplasm Incidence 60-70 years, Females Young females Elderly males Pathology Benign 30% risk of malignancy 65% risk of malignancy at 5 years Appearance Microcysts <2cm; Usually >6 in number, Central Stella the scar present Larger cysts, septations present Pleomorphic, nodules present, fish mouth\n appearance Calcification Central calcification Peripheral eggshell calcification Rare H a emorrhage Rare Rare Rare Pancreatic duct Normal Dilatation +/- Dilated, communication + Epithelium Glycogen-rich, cuboidal Columnar, mucin-producing Columnar, mucin-producing Aspirate Low CEA, amylase High CEA, Low amylase High CEA, High amylase</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the histological findings showing dense fibrosis and few remaining atrophic pancreatic acini, what is your diagnosis?", "options": [{"label": "A", "text": "Acute pancreatitis", "correct": false}, {"label": "B", "text": "Chronic pancreatitis", "correct": true}, {"label": "C", "text": "Pseudo cyst", "correct": false}, {"label": "D", "text": "Pancreatic carcinoma", "correct": false}], "correct_answer": "B. Chronic pancreatitis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689159032747-QTDP131002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic pancreatitis The given histological image showing fibrosis, atrophy and dropout of acini, and variable dilation of the pancreatic duct is suggestive of Chronic pancreatitis.</p>\n<p><strong>Highyeild:</strong></p><p>Chronic pancreatitis It is characterized by progressive inflammation and fibrosis of the pancreas , leading to permanent damage and functional impairment. The histological features of chronic pancreatitis typically include: Fibrosis : The pancreas shows significant fibrosis, which is the deposition of extracellular matrix proteins that can lead to scarring and loss of function. Atrophy and dropout of acin i: The acini, which are the functional units of the pancreas responsible for producing digestive enzymes, become atrophic and may drop out over time, leading to further loss of function. Dilation of pancreatic duct : The pancreatic duct may become dilated and distorted as a result of chronic inflammation and fibrosis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding congenital cysts of the pancreas except:", "options": [{"label": "A", "text": "It is multilocular", "correct": true}, {"label": "B", "text": "It develops due to anomalous development", "correct": false}, {"label": "C", "text": "Cyst is lined by columnar epithelium", "correct": false}, {"label": "D", "text": "Cysts are filled with clear and serous fluid", "correct": false}], "correct_answer": "A. It is multilocular", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is multilocular Congenital cyst of the pancreas is a rare condition that typically presents as a single cyst rather than a multilocular lesion.</p>\n<p><strong>Highyeild:</strong></p><p>Congenital cyst of the pancreas. It is a rare condition that occurs due to anomalous development of the pancreatic ducts. It is typically diagnosed in infants and children, but can also be seen in adults. Presents as unilocular, thin-walled cysts The cysts are lined by columnar epithelium and filled with clear or serous fluid. Often asymptomatic, but they can cause symptoms such as abdominal pain, nausea, and vomiting if they become large enough to compress adjacent organs. Diagnosis: Ultrasound, CT scan, or MRI Treatment: observation, surgical resection, or drainage of the cyst.</p>\n<p><strong>Extraedge:</strong></p><p>The prognosis for congenital cysts of the pancreas is generally good, with most patients experiencing complete resolution of symptoms after treatment. However, there is a risk of recurrence</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 39 year old patient presented with shortness of breath and a CT scan shows hilar lymphadenopathy. A bronchial biopsy was performed and the image is given below. What is your diagnosis?", "options": [{"label": "A", "text": "Sarcoidosis", "correct": true}, {"label": "B", "text": "Idiopathic Pulmonary fibrosis", "correct": false}, {"label": "C", "text": "Cryptogenic organizing pneumonia", "correct": false}, {"label": "D", "text": "Hyaline membrane disease", "correct": false}], "correct_answer": "A. Sarcoidosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686835370149-QTDP103004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Sarcoidosis The given clinical scenario and the histopathological picture showing well-formed non-necrotizing granulomas are suggestive of Sarcoidosis .</p>\n<p><strong>Highyeild:</strong></p><p>Sarcoidosis Idiopathic systemic disorder characterized by accumulation of lymphocytes and monocytes in many organs forming noncaseating, epithelioid granuloma and subsequent conformational changes in the involved organs. Diagnosis Elevated serum ACE levels Elevated CD4/CD8 ratio in BAL CXR shows bilateral adenopathy and coarse reticular opacities Gallium scan: Panda sign. Lambda sign Features: Mnemonic : SARCOIDS S: Schumann bodies A: Asteroid bodies R: RA like arthropathy C: Calcium level increased (due to an increase in 1-alpha-hydroxylase-mediated vitamin D activation in macrophages) O: Ocular Uveitis I: Interstitial Lung Disease D: Vitamin D activation S: Skin changes: Lupus pernio, erythema nodosum</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Idiopathic pulmonary fibrosis: It is a chronic and progressive lung disease characterized by the development of fibrosis, or scarring, in the lungs. Option: C. Cryptogenic organizing pneumonia: It is a form of interstitial lung disease that is characterized by the formation of granulation tissue within the alveolar spaces known as Masson bodies. Option: D. Hyaline membrane disease: It is a neonatal respiratory disorder characterized by the development of hyaline membranes within the lungs, which can lead to respiratory distress and hypoxemia.</p>\n<p><strong>Extraedge:</strong></p><p>Lofgren syndrome: Triad of erythema nodosum, Bilateral hilar lymphadenopathy on CXR, and Polyarticular arthritis Heerfordt’s syndrome: aka uveoparotid syndrome- Is associated with uveitis, parotid enlargement, and fever with or without facial nerve palsy.</p>\n<p><strong>Table:</strong></p><p>Histopathological findings of sarcoidosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following can be seen in sarcoidosis except:", "options": [{"label": "A", "text": "Non necrotizing granuloma", "correct": false}, {"label": "B", "text": "Schaumann bodies", "correct": false}, {"label": "C", "text": "Asteroid bodies", "correct": false}, {"label": "D", "text": "Ferruginous bodies", "correct": true}], "correct_answer": "D. Ferruginous bodies", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ferruginous bodies Ferruginous bodies are asbestos fibers that are coated with iron and are typically associated with asbestos exposure and asbestos-related diseases such as mesothelioma and asbestosis. They are not associated with sarcoidosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A, B & C: All are seen in sarcoidosis</p>\n<p><strong>Table:</strong></p><p>Histopathological findings of sarcoidosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding sarcoidosis except:", "options": [{"label": "A", "text": "Lung is the most common organ to be involved", "correct": false}, {"label": "B", "text": "BAL show CD8/CD 4 ratio of 4:1", "correct": true}, {"label": "C", "text": "Hilar and mediastinal lymph nodes are involved in most cases", "correct": false}, {"label": "D", "text": "It can cause unilateral or bilateral iriditis to uveitis", "correct": false}], "correct_answer": "B. BAL show CD8/CD 4 ratio of 4:1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>BAL show CD8/CD 4 ratio of 4:1 In sarcoidosis, the CD4/CD8 ratio in BAL fluid is usually greater than 3.5, whereas in healthy individuals, this ratio is less than 1.</p>\n<p><strong>Highyeild:</strong></p><p>Sarcoidosis Idiopathic systemic disorder characterized by accumulation of lymphocytes and monocytes in many organs forming noncaseating, epithelioid granuloma and subsequent conformational changes in the involved organs. Diagnosis Elevated serum ACE levels Elevated CD4/CD8 ratio in BAL CXR shows bilateral adenopathy and coarse reticular opacities Gallium scan: Panda sign. Lambda sign Features: Mnemonic : SARCOIDS S: Schumann bodies A: Asteroid bodies R: RA like arthropathy C: Calcium level increased (due to increase in 1-alpha-hydroxylase-mediated vitamin D activation in macrophages) O: Ocular Uveitis I: Interstitial Lung Disease D: Vitamin D activation S: Skin changes: Lupus pernio, erythema nodosum</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statement(s) is/are correct except:", "options": [{"label": "A", "text": "Increased PT in extrinsic pathways", "correct": false}, {"label": "B", "text": "Increased aPTT in intrinsic pathways", "correct": false}, {"label": "C", "text": "If the platelet count is > 1.5 lac/microL, then normal homeostasis is present", "correct": false}, {"label": "D", "text": "BT is normal in platelet abnormality", "correct": true}], "correct_answer": "D. BT is normal in platelet abnormality", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>BT is normal in platelet abnormality Bleeding time measures the function of platelets and so will be increased in platelet abnormality. Bleeding time (BT) (normal: 3-8 min) Q ● Time taken for a standardized skin puncture to stop bleeding. ● Tests the ability of vessels to vasoconstrict & platelets to form a hemostatic plug.</p>\n<p><strong>Highyeild:</strong></p><p>The prothrombin time (PT) assay assesses the function of the proteins in the extrinsic pathway (factors VII, X, V, II [prothrombin], and fibrinogen) . In brief, tissue factor, phospholipids, and calcium are added to plasma, and the time for a fibrin clot to form is recorded.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Increased PT in extrinsic pathways. Correct . Option: B. Increased aPTT in intrinsic pathways. Correct . Option: C. If the platelet count is > 1.5 lac/microL, then normal homeostasis is present. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The partial thromboplastin time (PTT) assay screens the function of the proteins in the intrinsic pathway (factors XII, XI, IX, VIII, X, V, II, and fibrinogen) . In this assay, clotting of plasma is initiated by the addition of negatively charged particles (e.g., ground glass) that activates factor XII (Hageman factor) together with phospholipids and calcium, and the time to fibrin clot formation is recorded.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following measures the intrinsic pathway?", "options": [{"label": "A", "text": "CT", "correct": false}, {"label": "B", "text": "aPTT", "correct": true}, {"label": "C", "text": "TT", "correct": false}, {"label": "D", "text": "Prothrombin time", "correct": false}], "correct_answer": "B. aPTT", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>aPTT Activated Partial thromboplastin time (aPTT) Q time taken for clotting when Kaolin/Silica is added to activate intrinsic pathway Q Other Other TESTS USED TO EVALUATE BLEEDING AND COAGULATION DISORDERS Test Description & Significance Tourniquet test (Hess test) Q ● BP cuff inflated to above diastolic pressure for 5 minutes ● Appearance of≥ 20 petechiae Q in 1 sq inch area of forearm indicates capillary fragility, thrombocytopenia, or platelet abnormalities. Clotting time (CT) (normal: 5-10 min) Q ● Time taken for the patient's blood to clot in a test tube. ● Very insensitive test ; Not used now a days. Clot retraction failure of clot retraction in 1–4 hours indicates thrombocytopenia or abnormal platelet function Q. Prothrombin time (PT)Q time taken for clotting to occur when tissue thromboplastin Q (brain extract) and calcium are added to the patient's plasma to activate extrinsic pathway Q Thrombin time (TT): time taken for clotting when thrombin is added to the patient's plasma to test for conversion of fibrinogen to fibrin (depends on fibrinogen levels) Q</p>\n<p><strong>Highyeild:</strong></p><p>The prothrombin time (PT) assay assesses the function of the proteins in the extrinsic pathway (factors VII, X, V, II [prothrombin], and fibrinogen) . In brief, tissue factor, phospholipids, and calcium are added to plasma, and the time for a fibrin clot to form is recorded.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CT. Clotting time, the time taken for a patient’s blood to clot in a day, is not used nowadays. Option: C. TT. Thrombin time is the time taken when thrombin is added to a patient's plasma for conversion of fibrinogen to fibrin (depending on fibrinogen levels). Option: D. Prothrombin time. Time is taken for clotting to occur when tissue thromboplastin and calcium are added to a patient's plasma to activate the extrinsic pathway.</p>\n<p><strong>Extraedge:</strong></p><p>The partial thromboplastin time (PTT) assay screens the function of the proteins in the intrinsic pathway (factors XII, XI, IX, VIII, X, V, II, and fibrinogen) . In this assay, clotting of plasma is initiated by the addition of negatively charged particles (e.g., ground glass) that activates factor XII (Hageman factor) together with phospholipids and calcium, and the time to fibrin clot formation is recorded.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following factors helps to stabilize the clot but does not cause spontaneous bleeding if deficient?", "options": [{"label": "A", "text": "VIII", "correct": false}, {"label": "B", "text": "XIII", "correct": false}, {"label": "C", "text": "IX", "correct": false}, {"label": "D", "text": "XII", "correct": true}], "correct_answer": "D. XII", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>XII Factor XII deficiency usually is not associated with hemorrhagic manifestations . It is noteworthy that myocardial infarction and thrombophlebitis have been observed in patients with severe factor XII deficiency, and that Hageman died of thromboembolic complications. It was originally thought that factor XII deficiency might actually predispose to thrombosis, possibly as the result of deficient the activation of fibrinolysis. However, more recent surveys indicate that factor XII deficiency is not associated with an excessive risk of thrombosis ; thrombotic events in factor XII–deficient patients may be explained by the presence of other prothrombotic gene defects in these patients.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. VIII. Causes Hemophilia A . Option: B. XIII. Deficiency of factor XIII leads to impaired clot stability , which can result in a bleeding disorder . Option: C. IX. Causes Hemophilia B.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An 11-year-old boy has elevated prothrombin and activated partial prothrombin time. What is the most likely defect?", "options": [{"label": "A", "text": "Defect in the extrinsic pathway", "correct": false}, {"label": "B", "text": "Defect in the intrinsic pathway", "correct": false}, {"label": "C", "text": "Defect in a common pathway", "correct": true}, {"label": "D", "text": "Defect in platelet function", "correct": false}], "correct_answer": "C. Defect in a common pathway", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Defect in a common pathway activated Partial thromboplastin time (aPTT) 26-37 sec ● Deficiencies or inhibitors of: Prekallikrein, high-molecular-weight kininogen Factors XII, XI, IX, VIII, X,V, II and I; ● Lupus inhibitors; heparin ; warfarin therapy Prothrombin time (PT) 12-15 sec ● Deficiencies or inhibitors of factors VII, X, and V; II and I; Q ● Lupus inhibitors; heparin; warfarin Q So, increase in both PT and aPTT will be due to common pathway defect. (Factor X,V,II,I deficiency)</p>\n<p><strong>Highyeild:</strong></p><p>Prothrombin Time 12-16 sec Activated Partial Thromboplastin Time 28-35 sec Measure EP + CP IP + CP Sample PPP {Platelet Poor Plasma} PPP Add in Thromboplastin Ca + PL Kaolin Ca + PL 1. ↑ PT Normal APTT - Extrinsic Pathway defect; Factor VII deficiency: Vit-K deficiency: Warfarin II. Norml PT ↑ APTT Intrinsic Pathway deficiency: Factor XII, XI, IX, VIII deficiency; Von Willebrand Disease III. 1PT ↑ APTT - Common Pathway defect: Factor X, V, II, I deficiency: Severe Liver disease; DIC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Defect in the extrinsic pathway. Incorrect . Option: B. Defect in the intrinsic pathway. Incorrect . Option: D. Defect in platelet function. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the most reliable test for screening haemophilia?", "options": [{"label": "A", "text": "Prothrombin time", "correct": false}, {"label": "B", "text": "Clotting time", "correct": false}, {"label": "C", "text": "Partial thromboplastin time", "correct": true}, {"label": "D", "text": "Clot retraction", "correct": false}], "correct_answer": "C. Partial thromboplastin time", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Partial thromboplastin time Hemophilia A and B are due to deficiency of Factor VIII and IX respectively, so aPTT is the best test. activated Partial thromboplastin time (aPTT) 26-37 sec ● Deficiencies or inhibitors of: Prekallikrein, high-molecular-weight kininogen Factors XII, XI, IX, VIII, X,V, II and I; ● Lupus inhibitors; heparin ; warfarin therapy Hemophillia A and B is due to deficiency of Factor VIII, IX so aptt is the best test.</p>\n<p><strong>Highyeild:</strong></p><p>Hemophilia A (Factor VIII Deficiency) Hemophilia A, the most common hereditary disease associated with life-threatening bleeding , is caused by mutations in factor VIII , an essential cofactor for factor IX in the coagulation cascade. Hemophilia A is inherited as an X-linked recessive trait and thus affects mainly males and homozygous females . In all symptomatic cases, there is a tendency toward easy bruising and massive haemorrhage after trauma or operative procedures. In addition, spontaneous haemorrhages frequently occur in regions of the body that are susceptible to trauma, particularly the joints , where they are known as hemarthroses . Recurrent bleeding into the joints leads to progressive deformities that can be crippling.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Prothrombin time. Incorrect . Option: B. Clotting time. Incorrect . Option: D. Clot retraction. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Petechiae are characteristically absent . Patients with haemophilia A have a prolonged PTT and a normal PT , results that point to an abnormality of the intrinsic coagulation pathway. Hemophilia A is treated with infusions of recombinant factor VIII .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "vWF protects factor?", "options": [{"label": "A", "text": "II", "correct": false}, {"label": "B", "text": "V", "correct": false}, {"label": "C", "text": "VIII", "correct": true}, {"label": "D", "text": "X", "correct": false}], "correct_answer": "C. VIII", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>VIII vWF is required for normal platelet adhesion and also acts as a carrier of factor VIII in the plasma 2 major functions of vWF are Platelet adhesion via GpIb/IX and stabilising factor VIII in circulation.</p>\n<p><strong>Highyeild:</strong></p><p>Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. II. Incorrect . Option: B. V. Incorrect . Option: D. X. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "10-day infant presented with large cephalic hematoma. His parents gave no history of trauma but severe umbilical bleeding during his childbirth. What is the most likely factor deficiency associated?", "options": [{"label": "A", "text": "vWF", "correct": false}, {"label": "B", "text": "Factor I def", "correct": false}, {"label": "C", "text": "Factor VIII def", "correct": false}, {"label": "D", "text": "Factor XIII def", "correct": true}], "correct_answer": "D. Factor XIII def", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor XIII def Factor XIII deficiency: Signs and symptoms of inherited factor XIII deficiency begin soon after birth , usually with abnormal bleeding from the umbilical cord stump . If the conditio13th not treated, affected individuals may have episodes of excessive and prolonged bleeding that can be life-threatening . Abnormal bleeding can occur after surgery or minor trauma. The condition can also cause spontaneous bleeding into the joints or muscles, leading to pain and disability . Women with inherited factor XIII deficiency tend to have heavy or prolonged menstrual bleeding (menorrhagia) and may experience recurrent pregnancy losses (miscarriages) . Other signs and symptoms of inherited factor XIII deficiency include nosebleeds, bleeding of the gums, easy bruising, problems with wound healing, and abnormal scar formation.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. vWF. von Willebrand disease (vWD), which is caused by a deficiency or dysfunction of von Willebrand factor, is typically characterized by mucocutaneous bleeding, such as nosebleeds or gum bleeding, rather than soft tissue bleeding . Option: B. Factor I def. Factor I deficiency , also known as fibrinogen deficiency , can lead to abnormal bleeding and impaired clotting but is less likely to cause a cephalic hematoma in a newborn. Option: C. Factor VIII def. Factor VIII dehaemorrhage and cause bleeding in newborns, it is less likely to present with a cephalic hematoma without a history of trauma.</p>\n<p><strong>Extraedge:</strong></p><p>Inherited factor XIII deficiency also increases the risk of spontaneous bleeding inside the skull (intracranial h aemorrhage), which is the leading cause of death in people with this condition .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a platelet-associated coagulation factor?", "options": [{"label": "A", "text": "vWF", "correct": false}, {"label": "B", "text": "Factor IX", "correct": true}, {"label": "C", "text": "Factor XI", "correct": false}, {"label": "D", "text": "Factor XIII", "correct": false}], "correct_answer": "B. Factor IX", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor IX Platelet-associated coagulation factors are: Fibrinogen, vWF, Factor V, XI, XIII & HMWK</p>\n<p><strong>Highyeild:</strong></p><p>Vitamin K-dependent coagulation factors : Factors II, VII, IX, and X . In Vitamin K deficiency and Warfarin usage: Factor 7 deficiency is first to decrease .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Incorrect . Option: C. Factor XI. Incorrect . Option: D. Factor XIII. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hemophilia C is a deficiency of", "options": [{"label": "A", "text": "Factor VIII", "correct": false}, {"label": "B", "text": "Factor IX", "correct": false}, {"label": "C", "text": "Factor X", "correct": false}, {"label": "D", "text": "Factor XI", "correct": true}], "correct_answer": "D. Factor XI", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor XI Hemophilia C is Factor XI deficiency</p>\n<p><strong>Highyeild:</strong></p><p>Hemophilia: The most common and important inherited deficiencies of coagulation factors affect factor VIII (haemophilia A) and factor IX (haemophilia B) . Hemophilia A (Factor VIII Deficiency) Hemophilia A , the most common hereditary disease associated with life-threatening bleeding, is caused by mutations in factor VIII , an essential cofactor for factor IX in the coagulation cascade. Hemophilia A is inherited as an X-linked recessive trait and thus affects mainly males and homozygous females . There is a tendency for easy bruising and massive haemorrhage after trauma or operative procedures . In addition, “spontaneous” haemorrhages frequently occur in regions of the body that are susceptible to trauma, particularly the joints , where they are known as hemarthroses . Recurrent bleeding into the joints leads to progressive deformities that can be crippling. Petechiae are characteristically absent . Patients with haemophilia A have a prolonged PTT and a normal PT . Factor VIII–specific assays are required for diagnosis. Hemophilia A is treated with infusions of recombinant factor VIII . Hemophilia B (Christmas Disease, Factor IX Deficiency) Severe factor IX deficiency produces a disorder clinically indistinguishable from factor VIII deficiency (haemophilia A). This should not be surprising, given that factors VIII and IX function together to activate factor It is inherited as an X-linked recessive trait . In about 15% of these patients, factor IX protein is present but is nonfunctional. As with haemophilia A, the PTT is prolonged and the PT is normal .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Factor VIII. Deficiency causes Hemophilia A . Option: B. Factor IX. Deficiency causes Hemophilia B/ Christmas Disease . Option: C. Factor X. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis of Christmas disease (named after the first patient identified with this condition, and not the holiday) is possible only by assay of the factor levels . The disease is treated with infusions of recombinant factor IX .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Levels of all coagulation factors are increased in pregnancy EXCEPT", "options": [{"label": "A", "text": "Factor VIII", "correct": false}, {"label": "B", "text": "Factor IX", "correct": false}, {"label": "C", "text": "Factor X", "correct": false}, {"label": "D", "text": "Factor XI", "correct": true}], "correct_answer": "D. Factor XI", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor XI Levels of factor XI are decreased in pregnancy.</p>\n<p><strong>Highyeild:</strong></p><p>In pregnancy, Factor II & V remain unchanged Factor XI & XIII are decreased Other coagulation factors increase making pregnancy a hypercoagulable state .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Factor VIII. Increased . Option: B. Factor IX. Increased . Option: C. Factor X. Increased .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Causes for DIC are all except:", "options": [{"label": "A", "text": "Anaerobic sepsis", "correct": false}, {"label": "B", "text": "Malignancy", "correct": false}, {"label": "C", "text": "Lymphoma", "correct": true}, {"label": "D", "text": "Leukemia", "correct": false}], "correct_answer": "C. Lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphoma Lymphoma is not the cause for DIC.</p>\n<p><strong>Highyeild:</strong></p><p>DIC is an acute, subacute, or chronic thrombo-hemorrhagic disorder characterized by the excessive activation of coagulation and the formation of thrombi in the microvasculature. It occurs as a secondary complication of many disorders. Sometimes the coagulopathy is localized to a specific organ or tissue. As a consequence of the thrombotic diathesis , there is the consumption of platelets, fibrin, and coagulation factors and, secondarily , activation of fibrinolysis . DIC can present with signs and symptoms relating to tissue hypoxia and infarction caused by microthrombi ; haemorrhage , due to depletion of factors required for hemostasis and activation of fibrinolytic mechanisms; or both. Two major mechanisms trigger DIC: Release of tissue factor or other procoagulants into the circulation. Widespread injury of endothelial cells. Common triggers: sepsis, major trauma, certain cancers, and obstetric complications . Etiology of DIC: table,tr,th,td {border:1px solid black;} Sepsis Immunologic disorders Bacterial: Staphylococci Q , streptococci, pneumococci, meningococci Q, gram-negative bacilli Q Viral, Mycotic, Parasitic, Rickettsial Q Acute hemolytic transfusion reaction, Transplant rejection, GVHD Q Trauma and tissue injury Drugs Brain injury (gunshot),Extensive burns, Fat embolism, Rhabdomyolysis Fibrinolytic agents, Warfarin (especially in neonates with protein C deficiency) Vascular disorders Envenomation Giant hemangiomas (Kasabach-Merritt syndrome)Q Snake, Insect bites Obstetrical complications Liver disease Abruptio placentae Q, Amniotic-fluid embolism, Dead fetus syndrome, Septic abortion Q Fulminant hepatic failure Q Cirrhosis, Fatty liver of pregnancy Q Cancer Miscellaneous Stomach Ca, Lung Ca, Acute promyelocytic leukemia (APML) Q Pancreas (most common) & Prostate Adenocarcinoma Q Shock, Respiratory distress syndrome, Massive transfusion Q</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Anaerobic sepsis. Correct . Option: B. Malignancy. Correct . Option: D. Leukemia. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Disseminated intravascular coagulation (DIC) differs from thrombotic thrombocytopenic purpura by-", "options": [{"label": "A", "text": "Significant numbers of schistocytes", "correct": false}, {"label": "B", "text": "A brisk reticulocytosis", "correct": false}, {"label": "C", "text": "Decreased coagulation factor levels", "correct": true}, {"label": "D", "text": "Significant thrombocytopenia", "correct": false}], "correct_answer": "C. Decreased coagulation factor levels", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Decreased coagulation factor levels Correct, seen only in DIC not in TTP .</p>\n<p><strong>Highyeild:</strong></p><p>DIC is an acute, subacute, or chronic thrombohemorrhagic disorder characterized by the excessive activation of coagulation and the formation of thrombi in the microvasculature. It occurs as a secondary complication of many disorders. Sometimes the coagulopathy is localized to a specific organ or tissue. As a consequence of the thrombotic diathesis , there is the consumption of platelets, fibrin, and coagulation factors and, secondarily , the activation of fibrinolysis . DIC can present with signs and symptoms relating to tissue hypoxia and infarction caused by microthrombi ; haemorrhage , due to depletion of factors required for hemostasis and activation of fibrinolytic mechanisms; or both. Two major mechanisms trigger DIC: Release of tissue factor or other procoagulants into the circulation. Widespread injury of endothelial cells. Common triggers: sepsis, major trauma, certain cancers, and obstetric complications .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Significant numbers of schistocytes. Seen in both, as both are causes of Microangiopathic hemolytic anaemia . Option: B. A brisk reticulocytosis. Seen in both, as both are causes of Microangiopathic hemolytic anaemia . Option: D. Significant thrombocytopenia. Seen in both.</p>\n<p><strong>Extraedge:</strong></p><p>Etiology of DIC: Sepsis Immunologic disorders Bacterial: Staphylococci Q , streptococci, pneumococci, meningococci Q, gram-negative bacilli Q Viral, Mycotic, Parasitic, Rickettsial Q Acute hemolytic transfusion reaction, Transplant rejection, GVHD Q Trauma and tissue injury Drugs Brain injury (gunshot),Extensive burns, Fat embolism, Rhabdomyolysis Fibrinolytic agents, Warfarin (especially in neonates with protein C deficiency) Vascular disorders Envenomation Giant hemangiomas (Kasabach-Merritt syndrome)Q Snake, Insect bites Obstetrical complications Liver disease Abruptio placentae Q, Amniotic-fluid embolism, Dead fetus syndrome, Septic abortion Q Fulminant hepatic failure Q Cirrhosis, Fatty liver of pregnancy Q Cancer Miscellaneous Stomach Ca, Lung Ca, Acute promyelocytic leukemia (APML) Q Pancreas (most common) & Prostate Adenocarcinoma Q Shock, Respiratory distress syndrome, Massive transfusion Q</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Not a cause for DIC -", "options": [{"label": "A", "text": "Septicemia", "correct": false}, {"label": "B", "text": "Visceral carcinoma", "correct": false}, {"label": "C", "text": "Cholera", "correct": true}, {"label": "D", "text": "Antepartum haemorrhage", "correct": false}], "correct_answer": "C. Cholera", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cholera Cholera is not a cause for DIC.</p>\n<p><strong>Highyeild:</strong></p><p>DIC is an acute, subacute, or chronic thrombohemorrhagic disorder characterized by the excessive activation of coagulation and the formation of thrombi in the microvasculature. It occurs as a secondary complication of many disorders. Sometimes the coagulopathy is localized to a specific organ or tissue. As a consequence of the thrombotic diathesis , there is the consumption of platelets, fibrin, and coagulation factors and, secondarily , the activation of fibrinolysis . DIC can present with signs and symptoms relating to tissue hypoxia and infarction caused by microthrombi ; haemorrhage , due to depletion of factors required for hemostasis and activation of fibrinolytic mechanisms; or both. Two major mechanisms trigger DIC: Release of tissue factor or other procoagulants into the circulation. Widespread injury of endothelial cells. Common triggers: sepsis, major trauma, certain cancers, and obstetric complications .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Septicemia. Correct . Option: B. Visceral carcinoma. Correct . Option: D. Antepartum haemorrhage. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Etiology of DIC: Sepsis Immunologic disorders Bacterial: Staphylococci Q , streptococci, pneumococci, meningococci Q, gram-negative bacilli Q Viral, Mycotic, Parasitic, Rickettsial Q Acute hemolytic transfusion reaction, Transplant rejection, GVHD Q Trauma and tissue injury Drugs Brain injury (gunshot),Extensive burns, Fat embolism, Rhabdomyolysis Fibrinolytic agents, Warfarin (especially in neonates with protein C deficiency) Vascular disorders Envenomation Giant hemangiomas (Kasabach-Merritt syndrome)Q Snake, Insect bites Obstetrical complications Liver disease Abruptio placentae Q, Amniotic-fluid embolism, Dead fetus syndrome, Septic abortion Q Fulminant hepatic failure Q Cirrhosis, Fatty liver of pregnancy Q Cancer Miscellaneous Stomach Ca, Lung Ca, Acute promyelocytic leukemia (APML) Q Pancreas (most common) & Prostate Adenocarcinoma Q Shock, Respiratory distress syndrome, Massive transfusion Q</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Bleeding in DIC is most closely related to -", "options": [{"label": "A", "text": "Raised fibrin degradation products level in blood", "correct": false}, {"label": "B", "text": "Prolong prothrombin time", "correct": false}, {"label": "C", "text": "Low serum fibrinogen level", "correct": true}, {"label": "D", "text": "Raised thrombin time", "correct": false}], "correct_answer": "C. Low serum fibrinogen level", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Low serum fibrinogen level Bleeding in DIC is most closely related to low fibrinogen level s in the blood and so the main aim of replacement therapy with blood products (FFP) in DIC is to replenish Fibrinogen .</p>\n<p><strong>Highyeild:</strong></p><p>DIC is an acute, subacute, or chronic thrombohemorrhagic disorder characterized by the excessive activation of coagulation and the formation of thrombi in the microvasculature. It occurs as a secondary complication of many disorders. Sometimes the coagulopathy is localized to a specific organ or tissue. As a consequence of the thrombotic diathesis , there is the consumption of platelets, fibrin, and coagulation factors and, secondarily , the activation of fibrinolysis . DIC can present with signs and symptoms relating to tissue hypoxia and infarction caused by microthrombi ; haemorrhage , due to depletion of factors required for hemostasis and activation of fibrinolytic mechanisms; or both. Two major mechanisms trigger DIC: Release of tissue factor or other procoagulants into the circulation. Widespread injury of endothelial cells. Common triggers: sepsis, major trauma, certain cancers, and obstetric complications .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Septicemia. Correct . Option: B. Visceral carcinoma. Correct . Option: D. Antepartum haemorrhage. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Etiology of DIC: Sepsis Immunologic disorders Bacterial: Staphylococci Q , streptococci, pneumococci, meningococci Q, gram-negative bacilli Q Viral, Mycotic, Parasitic, Rickettsial Q Acute hemolytic transfusion reaction, Transplant rejection, GVHD Q Trauma and tissue injury Drugs Brain injury (gunshot),Extensive burns, Fat embolism, Rhabdomyolysis Fibrinolytic agents, Warfarin (especially in neonates with protein C deficiency) Vascular disorders Envenomation Giant hemangiomas (Kasabach-Merritt syndrome)Q Snake, Insect bites Obstetrical complications Liver disease Abruptio placentae Q, Amniotic-fluid embolism, Dead fetus syndrome, Septic abortion Q Fulminant hepatic failure Q Cirrhosis, Fatty liver of pregnancy Q Cancer Miscellaneous Stomach Ca, Lung Ca, Acute promyelocytic leukemia (APML) Q Pancreas (most common) & Prostate Adenocarcinoma Q Shock, Respiratory distress syndrome, Massive transfusion Q</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Antithrombin is activated by:", "options": [{"label": "A", "text": "Heparin", "correct": true}, {"label": "B", "text": "Factor I", "correct": false}, {"label": "C", "text": "Factor V", "correct": false}, {"label": "D", "text": "Factor VIII", "correct": false}], "correct_answer": "A. Heparin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Heparin Antithrombin , a serine protease inhibitor, regulates coagulation by inactivating thrombin and other procoagulant enzymes, including factors Xa, IXa, XIa, and XIIa. Once bound to Heparin , the natural anticoagulant effect of Antithrombin is potentiated , resulting in the accelerated binding and inactivation of serine proteases, and factor Xa and thrombin in particular. The inhibition of these factors affects the common pathway of coagulation , resulting in decreased formation of thrombin and fibrin .</p>\n<p><strong>Highyeild:</strong></p><p>Prothrombin Time 12-16 sec Activated Partial Thromboplastin Time 28-35 sec Measure EP + CP IP + CP Sample PPP {Platelet Poor Plasma} PPP Add in Thromboplastin Ca + PL Kaolin Ca + PL I. s↑ PT Normal APTT - Extrinsic Pathway defect; Factor VII deficiency: Vit-K deficiency: Warfarin II. Norml PT ↑ APTT - Intrinsic Pathway deficiency; Factor XII, XI, IX, VIII deficiency: Von Willebrand Disease III. ↑ PT ↑ APTT - Common Pathway defect: Factor X, V. II, I deficiency: Severe Liver disease; DIC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Factor I. Incorrect . Option: C. Factor V. Incorrect . Option: D. Factor VIII. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Tumours causing thrombosis are all except:", "options": [{"label": "A", "text": "Stomach", "correct": false}, {"label": "B", "text": "Lung", "correct": false}, {"label": "C", "text": "Pancreas", "correct": false}, {"label": "D", "text": "Breast", "correct": true}], "correct_answer": "D. Breast", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Breast Thrombosis is breast carcinoma is the least common among the given Options.</p>\n<p><strong>Highyeild:</strong></p><p>Cancer-causing thrombosis are Stomach Ca, Lung Ca, Acute promyelocytic leukaemia (APML) M3 , Pancreas ( most common ) & Prostate Adenocarcinoma . MNEMONIC: SLAP tumours cause thrombosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Stomach. Causes thrombosis . Option: B. Lung. Causes thrombosis . Option: C. Pancreas. Causes thrombosis .</p>\n<p><strong>Extraedge:</strong></p><p>Table 4.2 Hypercoagulable States Primary (Genetic) Common Factor V mutation: factor V Leiden (Arg to Gln substitution in amino acid residue 506 leading to resistance to activated protein C) Prothrombin mutation (G20210A noncoding sequence variant leading to increased prothrombin levels) Increased levels of factors VIII, IX, XI, or fibrinogen (genetics unknown) Rare Antithrombin III deficiency Protein C deficiency Protein S deficiency Very Rare Fibrinolysis defects Homozygous homocystinuria (deficiency of cystathione B-synthetase) Secondary (Acquired) Strong Risk Factors for Thrombosis Prolonged bed rest or immobilization Myocardial infarction Atrial fibrillation Tissue injury (surgery, fracture, burn) Cancer Prosthetic cardiac valves Disseminated intravascular coagulation Heparin-induced thrombocytopenia Antiphospholipid antibody syndrome Other Risk Factors for Thrombosis Cardiomyopathy Nephrotic syndrome Hyperestrogenic states (pregnancy and postpartum) Oral contraceptive use Sickle cell anemia Smoking</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Treatment of antiphospholipid antibody syndrome:", "options": [{"label": "A", "text": "Warfarin for life", "correct": true}, {"label": "B", "text": "Warfarin for 1 year", "correct": false}, {"label": "C", "text": "IV immunoglobulin", "correct": false}, {"label": "D", "text": "Glucocorticoids", "correct": false}], "correct_answer": "A. Warfarin for life", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Warfarin for life After the first thrombotic event, APS patients should be placed on warfarin for life , aiming to achieve an international normalized ratio, INR , ranging from 2.5 to 3.5 , alone or in combination with 80 mg of aspirin daily . Pregnancy morbidity is prevented by a combination of heparin with aspirin 80 mg daily. IV immunoglobulin (IVIg) 400 mg/ kg every day for 5 days may also prevent abortions, whereas glucocorticoids are ineffective</p>\n<p><strong>Highyeild:</strong></p><p>Antiphospholipid antibody (APLA) This syndrome (previously called the lupus anticoagulant syndrome) has variable clinical manifestations, including recurrent thromboses, repeated miscarriages, cardiac valve vegetations, and thrombocytopenia . Fetal loss does not appear to be explained by thrombosis . Instead, it stems from antibody-mediated interference with the growth and differentiation of trophoblasts , leading to a failure of placentation. Antiphospholipid antibody syndrome is also a cause of renal microangiopathy , resulting in renal failure associated with multiple capillary and arterial thrombosis. Clinical presentations can include pulmonary embolism , pulmonary hypertension , valvular heart disease, stroke , bowel infarction , or renovascular hypertension . Anti–β2 -glycoprotein antibodies are suspected to have a significant role in APLA. Diagnosis of APLA is based on clinical features and demonstration of aPL antibodies in the serum. Management of APLA involves various forms of anticoagulation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Warfarin for 1 year. Incorrect . Option: C. IV immunoglobulin. Incorrect . Option: D. Glucocorticoids. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>The antibodies in patients with APLA also frequently result in a false-positive serologic test for syphilis because the antigen in the standard assay is embedded in cardiolipin, which cross-reacts with phospholipids of Treponema pallidum.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Not a feature of antiphospholipid antibody syndrome:", "options": [{"label": "A", "text": "Budd-Chiari syndrome", "correct": false}, {"label": "B", "text": "Coombs positive hemolytic anaemia", "correct": false}, {"label": "C", "text": "Libman sacks endocarditis", "correct": false}, {"label": "D", "text": "Priapism", "correct": true}], "correct_answer": "D. Priapism", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Priapism Priapism is not a typical feature of antiphospholipid antibody syndrome (APS). APS is an autoimmune disorder characterized by the presence of antiphospholipid antibodies (APLA) that can cause a wide range of clinical manifestations. The clinical features of APS are related to the increased risk of thrombotic events and can include deep vein thrombosis (DVT), pulmonary embolism (PE), stroke, myocardial infarction, and recurrent pregnancy loss . Budd-Chiari syndrome, Coombs-positive hemolytic anaemia, and Libman-Sacks endocarditis are all well-known clinical features of APS .</p>\n<p><strong>Highyeild:</strong></p><p>Antiphospholipid antibody (APLA) This syndrome (previously called the lupus anticoagulant syndrome) has variable clinical manifestations, including recurrent thromboses, repeated miscarriages, cardiac valve vegetations, and thrombocytopenia . Fetal loss does not appear to be explained by thrombosis . Instead, it stems from antibody-mediated interference with the growth and differentiation of trophoblasts , leading to a failure of placentation. Antiphospholipid antibody syndrome is also a cause of renal microangiopathy , resulting in renal failure associated with multiple capillary and arterial thrombosis. Clinical presentations can include pulmonary embolism , pulmonary hypertension , valvular heart disease, stroke , bowel infarction , or renovascular hypertension . Anti–β2 -glycoprotein antibodies are suspected to have a significant role in APLA. Diagnosis of APLA is based on clinical features and demonstration of aPL antibodies in the serum. Management of APLA involves various forms of anticoagulation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Budd-Chiari syndrome. Budd-Chiari syndrome is a rare condition that results from the obstruction of the hepatic veins, leading to liver congestion and liver failure . Coombs-positive Hemolytic ana Coombs-positive hemolytic anaemia is characterized by the destruction of red blood cells due to the production of autoantibodies . Option: C. Libman-Sacks endocarditis. Libman-Sacks endocarditis is a non-infectious inflammation of the heart valves that can lead to valve damage and heart failure .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All antibodies are seen in APLA except:", "options": [{"label": "A", "text": "Anti–β2 -glycoprotein", "correct": false}, {"label": "B", "text": "Anti-Prothrombin", "correct": true}, {"label": "C", "text": "Anti-Phospholipid", "correct": false}, {"label": "D", "text": "Anti-Cardiolipin", "correct": false}], "correct_answer": "B. Anti-Prothrombin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anti-Prothrombin Anti-Prothrombin antibodies are not seen in APL A . Antibodies seen in APLA are Lupus Anticoagulant (LAC) Anti-cardiolipin (aCL) Anti–β2 -glycoprotein Lupus Anticoagulant (LAC) & Anti-cardiolipin (aCL) are antiphospholipid antibodies.</p>\n<p><strong>Highyeild:</strong></p><p>Antiphospholipid antibody (APLA) This syndrome (previously called the lupus anticoagulant syndrome) has variable clinical manifestations, including recurrent thromboses, repeated miscarriages, cardiac valve vegetations, and thrombocytopenia . Fetal loss does not appear to be explained by thrombosis . Instead, it stems from antibody-mediated interference with the growth and differentiation of trophoblasts , leading to a failure of placentation. Antiphospholipid antibody syndrome is also a cause of renal microangiopathy , resulting in renal failure associated with multiple capillary and arterial thrombosis. Clinical presentations can include pulmonary embolism , pulmonary hypertension , valvular heart disease, stroke , bowel infarction , or renovascular hypertension . Anti–β2 -glycoprotein antibodies are suspected to have a significant role in APLA.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Anti–β2 -glycoprotein. Correct . Option: C. Anti-Phospholipid. Correct . Option: D. Anti-Cardiolipin. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis of APLA is based on clinical features and demonstration of aPL antibodies in the serum. Management of APLA involves various forms of anticoagulation .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about Virchow’s triad except-", "options": [{"label": "A", "text": "Concerned with the risk of intravascular thrombus", "correct": false}, {"label": "B", "text": "Depends on endothelial injury", "correct": false}, {"label": "C", "text": "Depends on platelet activation", "correct": true}, {"label": "D", "text": "Depends on stasis", "correct": false}], "correct_answer": "C. Depends on platelet activation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Depends on platelet activation Virchow’s triad does not depend upon platelet activation.</p>\n<p><strong>Highyeild:</strong></p><p>Thrombosis and Virchow’s Triad: Thrombosis results due to: Endothelial injury Stasis or Turbulent blood flow Hypercoagulability of the blood This is called Virchow's Triad . Arterial or cardiac thrombi usually begin at turbulence or endothelial injury sites , whereas venous thrombi characteristically occur at stasis sites . Thrombi are focally attached to the underlying vascular surface , particularly at the initiation . From here, arterial thrombi tend to grow retrograde , while venous thrombi extend in the direction of blood flow ; thus, BOTH propagate towards the heart .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Concerned with the risk of intravascular thrombus. Correct . Option: B. Depends on the endothelial injury. Correct . Option: D. Depends on stasis. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The Leiden factor is -", "options": [{"label": "A", "text": "Factor VI", "correct": false}, {"label": "B", "text": "Factor VIII", "correct": false}, {"label": "C", "text": "Factor IV", "correct": false}, {"label": "D", "text": "Factor V", "correct": true}], "correct_answer": "D. Factor V", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor V Leiden factor is factor V .</p>\n<p><strong>Highyeild:</strong></p><p>Factor V Leiden mutation is the most common cause of hypercoagulability. It is an autosomal dominant genetic condition that exhibits incomplete penetrance , meaning that not every person with the mutation will develop the disease. Single nucleotide mutation in factor V is called factor V Leiden . Among individuals with recurrent DVT , the frequency of this mutation is considerably higher, approaching 60% . The mutation results in the replacement of arginine with glutamine at amino acid 506 , which renders factor V resistant to cleavage and inactivation by protein C .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Factor VI. Incorrect . Option: B. Factor VIII. Incorrect . Option: C. Factor IV. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Coagulation normally is restricted to sites of vascular injury by:", "options": [{"label": "A", "text": "Circulating antithrombin III", "correct": false}, {"label": "B", "text": "Activation of fibrinolytic pathways", "correct": false}, {"label": "C", "text": "Activation of coagulation factors", "correct": true}, {"label": "D", "text": "Expression of thrombomodulin", "correct": false}], "correct_answer": "C. Activation of coagulation factors", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Activation of coagulation factors Coagulation normally is restricted to sites of vascular injury by: Limiting enzymatic activation to phospholipid surfaces provided by activated platelets or endothelium. Circulating inhibitors of coagulation factors, such as antithrombin III, whose activity is augmented by heparin-like molecules expressed on endothelial cells. Expression of thrombomodulin on normal endothelial cells, which binds thrombin and converts it to an anticoagulant. Activation of fibrinolytic pathways (e.g., by the association of t-PA with fibrin)</p>\n<p><strong>Highyeild:</strong></p><p>Normal endothelium shields coagulation factors from tissue factors in vessel walls and expresses multiple factors that actively oppose coagulation, most notably thrombomodulin , endothelial protein C receptor , heparin-like molecules , and tissue factor pathway inhibitor . Thrombomodulin and endothelial protein C receptor bind thrombin and protein C, respectively, in a complex on the endothelial cell surface. When bound in this complex, thrombin loses its ability to activate coagulation factors and platelets , and instead cleaves and activates protein C , a vitamin K–dependent protease that requires a cofactor, protein S. Activated protein C/protein S complex is a potent inhibitor of coagulation cofactors Va and VIIIa .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Circulating antithrombin III. Correct . Option: B. Activation of fibrinolytic pathways. Correct . Option: D. Expression of thrombomodulin. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "International Normalised Ratio (INR) is defined as:", "options": [{"label": "A", "text": "(PT patient/ PT control)ISI", "correct": true}, {"label": "B", "text": "(PT control/ PT patient)ISI", "correct": false}, {"label": "C", "text": "(PT patient/ PT control)1/ISI", "correct": false}, {"label": "D", "text": "(PT control/ PT patient)1/ISI", "correct": false}], "correct_answer": "A. (PT patient/ PT control)ISI", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>(PT patient/ PT control)ISI By adjusting for the ISI of a particular thromboplastin, an INR is defined as the PT ratio that would have been obtained if the WHO standard thromboplastin had been used . INR is calculated using the following formula: INR = (PT patient/ PT control) ISI</p>\n<p><strong>Highyeild:</strong></p><p>Factor V Leiden mutation is the most common cause of hypercoagulability. It is an autosomal dominant genetic condition that exhibits incomplete penetrance , meaning that not every person with the mutation will develop the disease. Single nucleotide mutation in factor V is called factor V Leiden . Among individuals with recurrent DVT , the frequency of this mutation is considerably higher, approaching 60% . The mutation results in the replacement of arginine with glutamine at amino acid 506 , which renders factor V resistant to cleavage and inactivation by protein C .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. (PT control/ PT patient)ISI. Incorrect . Option: C. (PT patient/ PT control)1/ISI. Incorrect . Option: D. (PT control/ PT patient)1/ISI. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not associated with increased prothrombin time?", "options": [{"label": "A", "text": "Severe factor seven deficiency", "correct": false}, {"label": "B", "text": "Liver failure", "correct": false}, {"label": "C", "text": "Von Willebrand disease", "correct": true}, {"label": "D", "text": "DIC", "correct": false}], "correct_answer": "C. Von Willebrand disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Von Willebrand disease In Von Willebrand’s disease, there is a slight deficiency of Factor VIII leading to an increase in aPTT and not PT . Others can lead to an increase in PT.</p>\n<p><strong>Highyeild:</strong></p><p>Features von Willebrand Disease Bernard Soulier Syndrome Glanzmann’s Thrombasthenia Inheritance Autosomal dominant Autosomal Recessive Autosomal Recessive Defects Type 1 and 3: Quantitative defects in vWF. Type 2 Qualitative defects in vWF. Absence of Gp Ib-IX-V receptor Absence of Gp IIb/IIIa receptor Mechanism Platelet adhesion defect despite having normal platelet counts. Factor VIII deficiency as vWF prevents degradation of factor VIII. Platelets adhesion defect. Platelet aggregation defect. Platelet counts Normal Normal/ Mild thrombocytopenia Normal Platelet morphology Normal Large platelets with dense granules Normal Bleeding time Prolonged Prolonged Prolonged Platelets aggregation test (Collagen, ADP, Thrombin) Normal Normal Abnormal Ristocetin Aggregation test Abnormal Normalises after the addition of normal serum . Abnormal Doesn’t normalise after the addition of normal serum . Normal vWF factor levels Decreased Normal Normal PT and aPTT Normal PT and prolonged aPTT Normal Normal MNEMONIC: B comes before G which is why Bernard Soullier shows the absence of Ib and Glanzmann Thrombasthenia shows the absence of IIb .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Severe factor seven deficiency. PT increased. Option: B. Liver failure. PT increased. Option: D. DIC. PT increased.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The clinical presentation of platelet-related bleeding may include all of the following except:", "options": [{"label": "A", "text": "Bruising", "correct": false}, {"label": "B", "text": "Nosebleeds", "correct": false}, {"label": "C", "text": "Gastrointestinal bleeding", "correct": false}, {"label": "D", "text": "Bleeding into the joints (hemarthroses)", "correct": true}], "correct_answer": "D. Bleeding into the joints (hemarthroses)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bleeding into the joints (hemarthroses) Bleeding into the joints (hemarthroses) is a feature of a coagulation factor deficiency and not platelet defects</p>\n<p><strong>Highyeild:</strong></p><p>Hemophilia A (Factor VIII Deficiency) Hemophilia A, the most common hereditary disease associated with life-threatening bleeding , is caused by mutations in factor VIII , an essential cofactor for factor IX in the coagulation cascade. Hemophilia A is inherited as an X-linked recessive trait and thus affects mainly males and homozygous females . In all symptomatic cases, there is a tendency toward easy bruising and massive haemorrhage after trauma or operative procedures. In addition, spontaneous haemorrhages frequently occur in regions of the body that are susceptible to trauma, particularly the joints , where they are known as hemarthroses . Recurrent bleeding into the joints leads to progressive deformities that can be crippling. Petechiae are characteristically absent .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Bruising. Correct . Option: B. Nosebleeds. Correct . Option: C. Gastrointestinal bleeding. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Patients with haemophilia A have a prolonged PTT and a normal PT , results that point to an abnormality of the intrinsic coagulation pathway. Hemophilia A is treated with infusions of recombinant factor VIII .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Rapid assessment of the entire coagulation pathway can be done by:", "options": [{"label": "A", "text": "Thromboelastography", "correct": true}, {"label": "B", "text": "Clotting Time", "correct": false}, {"label": "C", "text": "aPTT", "correct": false}, {"label": "D", "text": "Prothrombin Time", "correct": false}], "correct_answer": "A. Thromboelastography", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thromboelastography Rapid assessment of the entire coagulation pathway can be done by thromboelastography.</p>\n<p><strong>Highyeild:</strong></p><p>Thromboelastography (TEG): Rapid assessment of the entire coagulation pathway can be done by: Thromboelastography. table,tr,th,td {border:1px solid black;} TEG What is it? Normal values Abnormality in TEG Treatment R-value Reaction time: Time between initiation of coagulation cascade to initial formation of the clot 5-10 min Abnormality of Coagulation factors FFP K value Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm) 1-3 min Abnormality of Fibrinogen Cryoprecipitate α angle Rate of Clot formation & crosslinking, steeper the angle faster the rate of clot formation 53-72° Abnormality of Fibrinogen Cryoprecipitate MA Maximum Amplitude: Maximum clot strength, depends on Platelets 50-70mm Abnormality of Platelets Platelets Ly-30 Fibrinolysis after 30 min of MA 0-8% Excess Fibrinolysis Aminocaproic acid & Tranexamic acid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Clotting Time. Incorrect Option: C. aPTT. Measures Intrinsic pathway of coagulation . Option: D. Prothrombin Time. Measures extrinsic pathway of coagulation .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What does the marked area 'E' represent and what will be the management?", "options": [{"label": "A", "text": "MA, Maximum clot strength, platelet transfusion", "correct": false}, {"label": "B", "text": "K, Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm), Cryoprecipitate transfusion", "correct": true}, {"label": "C", "text": "R, Reaction time: Time between initiation of coagulation cascade to initial formation of a clot, FFP transfusion", "correct": false}, {"label": "D", "text": "Ly-30, Fibrinolysis after 30 min of MA, Tranexamic acid", "correct": false}], "correct_answer": "B. K, Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm), Cryoprecipitate transfusion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>K, Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm), Cryoprecipitate transfusion Marked areas in the image represent A: R, Reaction time: Time between initiation of coagulation cascade to initial formation of a clot, FFP transfusion. B: K, Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm), Cryoprecipitate transfusion. C: α angle, Rate of Clot formation & crosslinking, steeper angle faster is the rate of clot formation, Cryoprecipitate transfusion. D: MA, Maximum clot strength, platelet transfusion. E: Ly-30, Fibrinolysis after 30 min of MA, Tranexamic acid.</p>\n<p><strong>Highyeild:</strong></p><p>Thromboelastography (TEG): Rapid assessment of the entire coagulation pathway can be done by: Thromboelastography. table,tr,th,td {border:1px solid black;} TEG What is it? Normal values Abnormality in TEG Treatment R-value Reaction time: Time between initiation of coagulation cascade to initial formation of a clot 5-10 min Abnormality of Coagulation factors FFP K value Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm) 1-3 min Abnormality of Fibrinogen Cryoprecipitate α angle Rate of Clot formation & crosslinking, steeper the angle faster the rate of clot formation 53-72° Abnormality of Fibrinogen Cryoprecipitate MA Maximum Amplitude: Maximum clot strength, depends on Platelets 50-70mm Abnormality of Platelets Platelets Ly-30 Fibrinolysis after 30 min of MA 0-8% Excess Fibrinolysis Aminocaproic acid & Tranexamic acid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. MA, Maximum clot strength, platelet transfusion. Represented by ‘ D ’ in the image. Option: B. K, Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm), Cryoprecipitate transfusion. Represented by ‘ B ’ in the image. Option: C. R, Reaction time: Time between initiation of coagulation cascade to initial formation of a clot, FFP transfusion. Represented by ‘ A ’ in the image.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "You are an intern working at AIIMS casualty, a 24-year-old male came with a life-threatening RTA with a fracture of the base of the skull, and several injuries noted on the face, arms and torso. The patient's GCS is 8, BP is 90/60 mmHg and pulse is 120. The patient was given fluids and stabilised, his blood investigations were sent and are awaited. Your SR gave you the following Thromboelastography to interpret for this patient.", "options": [{"label": "A", "text": "MA is decreased, consider transfusing platelets", "correct": true}, {"label": "B", "text": "MA is increased, consider transfusing platelets", "correct": false}, {"label": "C", "text": "MA is decreased, consider transfusing FFP", "correct": false}, {"label": "D", "text": "MA is increased, consider transfusing FFP", "correct": false}], "correct_answer": "A. MA is decreased, consider transfusing platelets", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MA is decreased, consider transfusing platelets In the given image, the ‘ Test tube ’ pattern of TEG is seen, suggesting MA is decreased , thus platelet transfusion should be considered.</p>\n<p><strong>Highyeild:</strong></p><p>Thromboelastography (TEG): Rapid assessment of the entire coagulation pathway can be done by: Thromboelastography. table,tr,th,td {border:1px solid black;} TEG What is it? Normal values Abnormality in TEG Treatment R-value Reaction time: Time between initiation of coagulation cascade to initial formation of a clot 5-10 min Abnormality of Coagulation factors FFP K value Kinetic time: Time between the initial formation of the clot to specific clot firmness (20mm) 1-3 min Abnormality of Fibrinogen Cryoprecipitate α angle Rate of Clot formation & crosslinking, steeper the angle faster the rate of clot formation 53-72° Abnormality of Fibrinogen Cryoprecipitate MA Maximum Amplitude: Maximum clot strength, depends on Platelets 50-70mm Abnormality of Platelets Platelets Ly-30 Fibrinolysis after 30 min of MA 0-8% Excess Fibrinolysis Aminocaproic acid & Tranexamic acid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. MA is increased, consider transfusing platelets. False, MA is decreased , not increased. Option: C. MA is decreased, consider transfusing FFP. False, Platelets are transfused when MA is decreased , not FFP. Option: D. MA is increased, consider transfusing FFP. False, MA is decreased , not increased.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 38 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are true, except?", "options": [{"label": "A", "text": "NADPH oxidase acts via superoxide ions", "correct": false}, {"label": "B", "text": "Chediak-Higashi syndrome is due to defective phagolysosome formation", "correct": false}, {"label": "C", "text": "Chronic Granulomatous Disease is due to a defect in the LYST gene", "correct": true}, {"label": "D", "text": "Myeloperoxidase action is mainly due to OCI-", "correct": false}], "correct_answer": "C. Chronic Granulomatous Disease is due to a defect in the LYST gene", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic Granulomatous Disease is due to a defect in the LYST gene</p>\n<p><strong>Highyeild:</strong></p><p>Chediak Higashi Syndrome Autosomal recessive condition. A defect in the LYST gene results in defective phagolysosome formation , impairing phagocyte function and susceptibility to infections . The main leukocyte abnormalities are neutropenia (decreased numbers of neutrophils), defective degranulation , and delayed microbial killing . Leukocytes contain giant granules , which can be readily seen in peripheral blood smears and are thought to result from aberrant phagolysosome fusion. In addition, there are abnormalities in melanocytes (leading to albinism ), cells of the nervous system (associated with nerve defects ), and platelets (causing bleeding disorders ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. NADPH oxidase acts via superoxide ions. True . Option: B. Chediak-Higashi syndrome is due to defective phagolysosome formation. True . Option: D. Myeloperoxidase action is mainly due to OCI- True .</p>\n<p><strong>Extraedge:</strong></p><p>Chronic Granulomatous Disease Inherited defects in microbicidal activity . The importance of oxygen-dependent bactericidal mechanisms is shown by the existence of a group of congenital disorders called chronic granulomatous disease , which are characterised by defects in bacterial killing and render patients susceptible to recurrent bacterial infection . Chronic granulomatous disease results from inherited defects in the genes encoding components of phagocyte oxidase (PHOX gene) , the phagolysosomal enzyme that generates superoxide (O 2•), causing a defective Respiratory burst . The most common variants are an X-linked defect in one of the membrane-bound components ( gp91phox ) and autosomal recessive defects in the genes encoding two cytoplasmic components ( p47phox and p67phox ). The Nitroblue tetrazolium test is helpful for screening . Defects in neutrophil function , as in chronic granulomatous disease, increase susceptibility to infections with aureus, some gram-negative bacteria, and fungi .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 7-year-old child presents with a complaint of pain in the throat; the pain worsens while swallowing. Diagnosed with acute pharyngitis. Which of the following is incorrect?", "options": [{"label": "A", "text": "Neutrophils will be first to arrive at the lesion", "correct": false}, {"label": "B", "text": "Vasodilation will cause erythema", "correct": false}, {"label": "C", "text": "Granuloma will be present", "correct": true}, {"label": "D", "text": "If group A beta-hemolytic bacteria are present, it may cause rheumatic fever", "correct": false}], "correct_answer": "C. Granuloma will be present", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Granuloma will be present As it is an acute condition, granuloma will not be formed. Granuloma is seen in chronic inflammation .</p>\n<p><strong>Highyeild:</strong></p><p>In the usual hematoxylin and eosin preparations, the activated macrophages in granulomas have pink granular cytoplasm with indistinct cell boundaries. They are called epithelioid cells because they resemble epithelia. A collar of lymphocytes surrounds the aggregates of epithelioid macrophages. Older granulomas may have a rim of fibroblasts and connective tissue . Frequently, but not invariably, multinucleated giant cells 40 to 50 µm in diameter are found in granulomas called Langhans giant cells . They consist of a large mass of cytoplasm and many nuclei , and they derive from the fusion of multiple activated macrophages. In granulomas associated with certain infectious organisms (most classically Mycobacterium tuberculosis ), a combination of hypoxia and free radical-mediated injury leads to a central zone of necrosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Neutrophils will be the first to arrive at the lesion. True, because neutrophils have the maximum number among the WBCs in blood, they will first come at the site of inflammation. Option: B. Vasodilation will cause erythema. Due to inflammation, there will be vasodilation which will cause erythema. Option: D. If group A beta-hemolytic bacteria are present, it may cause rheumatic fever. True, infection with group A beta-hemolytic bacteria can cause rheumatic fever.</p>\n<p><strong>Extraedge:</strong></p><p>Grossly , this has a granular, cheesy appearance and is therefore called caseous necrosis . Microscopically , this necrotic material appears as amorphous, structureless, eosinophilic, granular debris with a complete loss of cellular details . The granulomas in Crohn's disease, sarcoidosis, and foreign body reactions tend NOT to have necrotic centres and are said to be noncaseating . The healing of granulomas is accompanied by fibrosis.</p>\n<p><strong>Table:</strong></p><p>Defects in Innate Immunity Disease Defect Defects in Leukocyte Function Leukocyte adhesion deficiency\n I Defective leukocyte adhesion because\n of mutations in ẞ chain of CD11/CD18 integrins Leukocyte adhesion deficiency\n 2 Defective leukocyte adhesion\n because of mutations in fucosyl transferase required for synthesis of\n sialylated oligosaccharide (receptor for selectins) Chédiak-Higashi syndrome Decreased leukocyte functions\n because of mutations affecting protein involved in lysosomal membrane traffic Chronic granulomatous disease X-linked Decreased oxidative burst Phagocyte oxidase (membrane component) Phagocyte oxidase\n (cytoplasmic components) Myeloperoxidase deficiency Decreased microbial killing\n because of defective MPO-H₂O₂ system Defects in the Complement\n System C2, C4 deficiency Defective classical pathway\n activation results in reduced resistance to infection and reduced clearance\n of immune complexes C3 deficiency Defects in all complement\n functions Deficiency of complement\n regulatory proteins Excessive complement\n activation; clinical syndromes include angioedema, paroxysmal hemoglobinuria,\n others In granulomas associated with certain\n infectious organisms (most classically Mycobacterium tuberculosis ),\n a combination of hypoxia and free radical-mediated injury leads to a central\n zone of necrosis . Examples of Diseases With\n Granulomatous Inflammation Disease Cause Tissue Reaction Tuberculosis Mycobacterium tuberculosis Caseating granuloma (tubercle):\n focus of activated macrophages (epithelioid cells). rimmed by fibroblasts,\n lymphocytes, histiocytes, occasional Langhans giant cells; central necrosis\n with amorphous granular debris; acid-fast bacilli Leprosy Mycobacterium leprae Acid-fast bacilli in\n macrophages; noncaseating granulomas Syphilis Treponema pallidum Gumma: microscopic to grossly\n visible lesion, enclosing wall of histiocytes; plasma cell infiltrate;\n central cells are necrotic without loss of cellular outline Cat-scratch disease Gram-negative bacillus Rounded or stellate granuloma\n containing central granular debris and recognizable neutrophils; giant cells\n uncommon Sarcoidosis Unknown etiology Noncaseating granulomas with\n abundant activated macrophages Crohn disease (inflammatory\n bowel disease) Immune reaction against\n intestinal bacteria, possibly self antigens Occasional noncaseating\n granulomas in the wall of the intestine, with dense chronic inflammatory\n infiltrate Caseating granuloma: Only four examples are to be remembered 1. TB 2. Syphilis 3. Histoplasma 4. Coccidiomycosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 7-month-old boy presented with a two-day history of fever and abscess over the neck. The mother reveals that the child had similar recurrent infections in the past. The result of the nitroblue tetrazolium dye reduction test was abnormal. Which is the most likely diagnosis?", "options": [{"label": "A", "text": "Tuberculosis", "correct": false}, {"label": "B", "text": "Chronic granulomatous disease", "correct": true}, {"label": "C", "text": "Severe combined Immunodeficiency", "correct": false}, {"label": "D", "text": "Chediak higashi syndrome", "correct": false}], "correct_answer": "B. Chronic granulomatous disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic granulomatous disease The given clinical history and abnormal nitroblue tetrazolium dye reduction test most likely suggest chronic granulomatous disease . The condition usually manifests with recurrent pyogenic infections with catalase-positive organisms in the first year of life .</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Granulomatous Disease Inherited defects in microbicidal activity . The importance of oxygen-dependent bactericidal mechanisms is shown by the existence of a group of congenital disorders called chronic granulomatous disease , which are characterised by defects in bacterial killing and render patients susceptible to recurrent bacterial infection . Chronic granulomatous disease results from inherited defects in the genes encoding components of phagocyte oxidase (PHOX gene) , the phagolysosomal enzyme that generates superoxide (O 2•), causing a defective Respiratory burst . The most common variants are an X-linked defect in one of the membrane-bound components ( gp91phox ) and autosomal recessive defects in the genes encoding two cytoplasmic components ( p47phox and p67phox ).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Tuberculosis. History and Nitroblue tetrazolium test don’t go in favour of TB. Option: B. Severe combined Immunodeficiency. XR > AR condition . Characterised by IL-Receptor mutation and ADA deficiency , B, T, and NK cells are absent, and the child fails to survive beyond seven years. Option: D. Chediak higashi syndrome. Autosomal recessive . Defect in LYST gene (chromosome 1) . Increases infection risk, Increased bleeding tendencies, Albinism</p>\n<p><strong>Extraedge:</strong></p><p>The name of this disease comes from the macrophage-rich chronic inflammatory reaction that tries to control the infection when the initial neutrophil defence is inadequate. This often leads to c tions of activated macrophages that wall off the microbes, forming granulomas. The Nitroblue tetrazolium test is helpful for screening . Defects in neutrophil function , as in chronic granulomatous disease, increase susceptibility to infections with aureus, some gram-negative bacteria, and fungi .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are genetic susceptibility for type 1 diabetes except:", "options": [{"label": "A", "text": "HLA DR3/DR4 haplotype", "correct": false}, {"label": "B", "text": "Polymorphism for CTLA4 and PTPN22", "correct": false}, {"label": "C", "text": "Insulin with VNTR", "correct": false}, {"label": "D", "text": "Mutation in KCNJ11", "correct": true}], "correct_answer": "D. Mutation in KCNJ11", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mutation in KCNJ11 KCNJ11 (Potassium Inwardly Rectifying Channel, Subfamily J, Member 11) is a gene associated with a rare form of diabetes called neonatal diabetes. This gene is not typically associated with an increased risk of type 1 diabetes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . HLA DR3/DR4 haplotype: The presence of the HLA DR3 and DR4 haplotypes is associated with an increased risk of developing type 1 diabetes. Option: B. Polymorphism for CTLA4 and PTPN22: Polymorphisms in genes encoding proteins such as CTLA4 and PTPN22 have been implicated in the development of type 1 diabetes. These genetic variations can affect immune system regulation and increase the risk of autoimmunity. Option: C. Insulin with VNTR: Insulin gene VNTR polymorphism has been studied in relation to type 1 diabetes susceptibility. Certain VNTR alleles have been associated with an increased risk of developing type 1 diabetes.</p>\n<p><strong>Table:</strong></p><p>Type 1 Vs Type 2 diabetes Type 1 Type 2 Cause Autoimmune T-cell–mediated destruction of β cells Increased resistance to insulin, progressive\n pancreatic β-cell failure Insulin requirement Always Sometimes Age <30 years >40 years Obesity No Yes Genetic predisposition Relatively weak Relatively strong Association with the HLA system Yes, HLA-DR4 and DR3 No Glucose intolerance Severe Mild to moderate Insulin Sensitivity High Low Ketoacidosis Common rare Beta cell numbers in the islets Decreased Variable Serum insulin level Decreased Increased initially but decreases in advanced\n disease Classic symptoms (polydipsia, polyuria,\n polyphagia, weight loss) Common Sometimes Histology Islet leukocytic infiltrate Islet amyloid polypeptide deposits</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most common cause of death in diabetes is-", "options": [{"label": "A", "text": "Nephropathy", "correct": false}, {"label": "B", "text": "Myocardial infarction", "correct": true}, {"label": "C", "text": "Neuropathy", "correct": false}, {"label": "D", "text": "Ketoacidosis", "correct": false}], "correct_answer": "B. Myocardial infarction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myocardial infarction Myocardial infarction, caused by atherosclerosis of the coronary arteries, is the most common cause of death in diabetics.</p>\n<p><strong>Highyeild:</strong></p><p>Complications of diabetes mellitus Complications Description Cardiovascular complications ● Coronary artery disease ● Stroke ● Peripheral artery disease Nephropathy ● Diabetic nephropathy (kimmelstiel Wilson lesions) Neuropathy ● Diabetic peripheral neuropathy ● Autonomic neuropathy Eye disease ● Diabetic retinopathy Skin complications ● Diabetic foot ulcers ● Infections ● Slow wound healing ● Fungal infections ● Bacterial infections ● Skin discolouration ● Dermopathy ● Necrobiosis lipoidica diabeticorum Neuropsychiatric complications ● Depression ● Cognitive decline ● Increased risk of dementia ● Anxiety ● Eating disorders ● Sleep disorders ● Sexual dysfunction Gastrointestinal complications ● Gastroparesis (delayed stomach emptying) ● Diabetic diarrhoea ● Fatty liver disease ● Pancreatitis ● Gallbladder disease</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most constant histological features of diabetes that can be seen in the skin, smooth muscle, retina, and kidney are?", "options": [{"label": "A", "text": "Endothelial cell proliferation", "correct": false}, {"label": "B", "text": "Dense inflammatory infiltrate", "correct": false}, {"label": "C", "text": "Thickening of basement membrane", "correct": true}, {"label": "D", "text": "Profuse edema", "correct": false}], "correct_answer": "C. Thickening of basement membrane", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thickening of basement membrane The most constant histological feature of diabetes that can be seen in the skin, smooth muscle, retina, and kidney is the thickening of the basement membrane. It is caused by the accumulation of certain substances, such as advanced glycation end products (AGEs) and extracellular matrix component s, as a result of chronic hyperglycemia. This thickening can impair the normal function of these tissues and contribute to the development of diabetic complications.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Endothelial cell proliferation: While endothelial cell proliferation can occur in certain diabetic complications, such as diabetic retinopathy and diabetic nephropathy, it is not a consistent histological feature seen in all affected tissues, including the skin and smooth muscle. Option: B. Dense inflammatory infiltrate: While inflammation can be present in some diabetic complications, such as diabetic nephropathy, it is not a constant histological feature seen in all affected tissues. Option: D. Profuse edema: Edema, or fluid accumulation, can occur in certain diabetic complications, such as diabetic nephropathy, but it is not a constant histological feature observed in all tissues affected by diabetes.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following histological features seen in diabetic nephropathy except:", "options": [{"label": "A", "text": "Thickening of basement membrane", "correct": false}, {"label": "B", "text": "Diffuse mesangial sclerosis", "correct": false}, {"label": "C", "text": "Nodular glomerulosclerosis", "correct": false}, {"label": "D", "text": "Cortical sclerosis", "correct": true}], "correct_answer": "D. Cortical sclerosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cortical sclerosis Cortical sclerosis, or interstitial fibrosis, is not a characteristic histological feature of diabetic nephropathy. It refers to the replacement of normal kidney tissue with fibrous scar tissue in the cortical region. While chronic kidney disease can lead to cortical sclerosis, it is not specific to diabetic nephropathy.</p>\n<p><strong>Highyeild:</strong></p><p>Diabetic glomerulonephropathy Pathophysiology : Features: Nodular sclerosis Diffuse glomerular involvement Thickening of glomerular basement membrane Mesangial expansion Hyaline arteriolosclerosis Proteinuria Progression to end-stage renal disease</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A, B, C: All are features of diabetic nephropathy</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 47-year-old patient is on irregular medication of oral hypoglycemic drugs, and at present has a random blood sugar of 200 mg/dl. At present he has oliguria. A renal biopsy was performed and the histopathological diagram is shown below. What is the likely diagnosis?", "options": [{"label": "A", "text": "Amyloidosis", "correct": false}, {"label": "B", "text": "Diabetic glomerulopathy", "correct": true}, {"label": "C", "text": "Focal segmental glomerulosclerosis", "correct": false}, {"label": "D", "text": "Minimal change disease", "correct": false}], "correct_answer": "B. Diabetic glomerulopathy", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686835202741-QTDP160006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Diabetic glomerulopathy The given clinical scenario of irregular medication of oral hypoglycemic drugs, elevated random blood sugar levels, and the histopathological finding of nodular sclerosis with oliguria suggest the diagnosis of diabetic glomerulopathy. The presence of nodular sclerosis, or Kimmelstiel-Wilson nodules , is a hallmark feature of diabetic glomerulopathy.</p>\n<p><strong>Highyeild:</strong></p><p>Diabetic glomerulonephropathy Pathophysiology : Features: Nodular sclerosis Diffuse glomerular involvement Thickening of glomerular basement membrane Mesangial expansion Hyaline arteriolosclerosis Proteinuria Progression to end-stage renal disease</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Amyloidosis: In amyloidosis, the glomeruli often show a homogeneous, amorphous deposition of amyloid material rather than nodular sclerosis seen in the image. Option: C. Focal segmental glomerulosclerosis: FSGS can cause sclerosis, but it typically presents as focal and segmental areas of sclerosis, not the diffuse nodular sclerosis seen in the image. Option: D. Minimal change disease: MCD is a kidney disorder characterized by minimal changes observed under the microscope. It typically affects children and is associated with nephrotic syndrome.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The Karyotype of a patient shows the following, what is the clinical abnormality that is expected:", "options": [{"label": "A", "text": "Turner syndrome", "correct": true}, {"label": "B", "text": "Kallmann syndrome", "correct": false}, {"label": "C", "text": "Androgen insensitivity syndrome", "correct": false}, {"label": "D", "text": "Down syndrome", "correct": false}], "correct_answer": "A. Turner syndrome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482493-QTDP036001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Turner syndrome</p>\n<p><strong>Highyeild:</strong></p><p>Turner syndrome: The given image indicates the XO genotype . Turner syndrome results from complete or partial monosomy of the X chromosome and is characterized by hypogonadism in phenotypic females . It is important to appreciate the karyotypic heterogeneity associated with Turner syndrome because it is responsible for significant variations in phenotype . In patients in whom the proportion of 45, X cells is high, the phenotypic changes are more severe than in those who have readily detectable mosaicism. The latter may have an almost normal appearance and may present only with primary amenorrhea. The classical presentation includes: Short stature Webbed neck Hypothyroidism, Insulin resistance Cubitus valgus Primary amenorrhea Streak ovaries Edema of the dorsum of the hand and foot due to lymph stasis and sometimes swelling of the nape of the neck . Congenital heart disease is also common, with left-sided cardiovascular abnormalities . In Turner syndrome, the most common cardiac anomaly seen is Bicuspid aortic valve>> Coarctation of the aorta . At puberty, there is a failure to develop normal secondary sex characteristics . The genitalia remains infantile , breast development is inadequate , and there is little pubic hair.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Kallmann syndrome. Presents with an impaired sense of smell with a hormonal disorder that delays or prevents puberty . The hormonal disorder is due to the underdevelopment of specific neurons, or nerves, in the brain that signals the hypothalamus. Other features include absent breast development, the uterus being present, syndactyly, cleft palate, or cleft lip . Option: C. Androgen insensitivity syndrome. When a person who is genetically male ( XY ) is resistant to male hormones (androgens ). As a result, the person has some of the physical traits of a woman, but the genetic makeup of a man . Option: D. Down syndrome. Trisomy of chromosome 21, is associated with signs and symptoms like Intellectual disability, epicanthic folds, Simian crease, Sandal gap, and Predisposition to leukemia .</p>\n<p><strong>Extraedge:</strong></p><p>5-10% of patients with Turner syndrome have Y chromosome sequences either as a complete Y chromosome (e.g., 45, X/46, XY karyotype) or as fragments of Y chromosomes translocated on other chromosomes. These patients are at a higher risk for the development of a gonadal tumor (gonadoblastoma) .</p>\n<p><strong>Table:</strong></p><p>TURNER AND KLINEFELTER SYNDROME</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In the given image of Fluorescent in situ hybridization (FISH) analysis of an interphase nucleus using locus-specific probes to chromosome 13 (green) and chromosome 21 (red), revealing three red signals. This is consistent with the:", "options": [{"label": "A", "text": "Trisomy 13", "correct": false}, {"label": "B", "text": "Trisomy 21", "correct": true}, {"label": "C", "text": "Monosomy 13", "correct": false}, {"label": "D", "text": "Monosomy 21", "correct": false}], "correct_answer": "B. Trisomy 21", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482523-QTDP036002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Trisomy 21</p>\n<p><strong>Highyeild:</strong></p><p>Trisomy 21 (Down Syndrome) Down syndrome is the most common of the chromosomal disorders and is a significant cause of intellectual disability . FISH with chromosome 21–specific probes reveal the extra copy of chromosome 21 in such cases. The most common cause of trisomy and therefore of Down syndrome is meiotic nondisjunction . Maternal age has a strong influence on the incidence of trisomy 21 . The classical presentation includes: Flat facial profile Epicanthic folds Oblique palpebral fissures Simian crease Sandal gap Predisposition to leukemia Intellectual disability</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. In the above FISH 3 green (chromosome 13) would have signified Patau syndrome . Option: C. In the above FISH, one green (chromosome 13) would have signified monosomy 13 . Option: D. In the above FISH one red (chromosome 21) would have signified monosomy 21 .</p>\n<p><strong>Extraedge:</strong></p><p>The most frequent forms of congenital heart disease in Down syndrome are atrioventricular septal defects . Cardiac problems are responsible for the majority of the deaths in infancy and early childhood. Several other congenital malformations, including atresias of the esophagus and small bowel , are also common. Children with trisomy 21 have a high risk of developing Leukemia ; there is a 20-fold increased risk of developing acute B lymphoblastic leukemias and a 500-fold increased risk of acute myeloid leukemias . The latter, most commonly, is acute megakaryoblastic leukemia (M7) . Almost all patients with trisomy 21 older than age 4 0 develop neuropathologic changes characteristic of Alzheimer’s disease , a degenerative disorder of the brain. ( PYQ ) Patients with Down syndrome have abnormal immune responses that predispose them to serious infections , particularly of the lungs , and to thyroid autoimmunity .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A married middle age female gives a history of repeated abortion for the past 3yrs the prenatal karyogram of conceptus is given below this karyogram suggests?", "options": [{"label": "A", "text": "Klinefelter syndrome", "correct": false}, {"label": "B", "text": "Patau syndrome", "correct": false}, {"label": "C", "text": "Turner syndrome", "correct": false}, {"label": "D", "text": "Down syndrome", "correct": true}], "correct_answer": "D. Down syndrome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482557-QTDP036003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Down syndrome The given karyogram shows chromosome 21 as 3 instead of a pair (of 2) it is called trisomy 21 (Down Syndrome)</p>\n<p><strong>Highyeild:</strong></p><p>Trisomy 21 (Down Syndrome) Down syndrome is the most common of the chromosomal disorders and is a significant cause of intellectual disability . FISH with chromosome 21–specific probes reveal the extra copy of chromosome 21 in such cases. The most common cause of trisomy and therefore of Down syndrome is meiotic nondisjunction . Maternal age has a strong influence on the incidence of trisomy 21 . The classical presentation includes: Flat facial profile Epicanthic folds Oblique palpebral fissures Simian crease Sandal gap Predisposition to leukemia Intellectual disability</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Klinefelter syndrome. In the above karyogram, 2 copies of chromosome X and a copy of chromosome Y would have signified Klinefelter syndrome . Option: B. Patau syndrome. In the above karyogram, 3 copies of chromosome 13 would have signified Patau syndrome . Option: C. Turner syndrome. In the above karyogram, 1 copy of chromosome X would have signified Turner syndrome .</p>\n<p><strong>Extraedge:</strong></p><p>The most frequent forms of congenital heart disease in Down syndrome are atrioventricular septal defects . Cardiac problems are responsible for the majority of the deaths in infancy and early childhood. Several other congenital malformations, including atresias of the esophagus and small bowel , are also common. Children with trisomy 21 have a high risk of developing Leukemia ; there is a 20-fold increased risk of developing acute B lymphoblastic leukemias and a 500-fold increased risk of acute myeloid leukemias . The latter, most commonly, is acute megakaryoblastic leukemia (M7) . Almost all patients with trisomy 21 older than age 4 0 develop neuropathologic changes characteristic of Alzheimer's disease , a degenerative disorder of the brain. ( PYQ ) Patients with Down syndrome have abnormal immune responses that predispose them to serious infections , particularly of the lungs , and to thyroid autoimmunity .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An 18 years old female presents with a complaint of primary amenorrhea. She has a short height, a webbed neck, and wide-spaced nipples. What is the most common congenital cardiac defect in this syndrome?", "options": [{"label": "A", "text": "Coarctation of the aorta", "correct": false}, {"label": "B", "text": "Bicuspid aortic valve", "correct": true}, {"label": "C", "text": "Transposition of great arteries", "correct": false}, {"label": "D", "text": "VSD", "correct": false}], "correct_answer": "B. Bicuspid aortic valve", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bicuspid aortic valve Turner syndrome : A chromosomal disorder in which a female is born with only one X chromosome ( XO ). Pointers to the diagnosis of Turner syndrome Age group Features Intrauterine period Increased neck translucency, cystic hygroma Infancy Cystic hygroma, lymphedema, coarctation of aorta, partial anomalous pulmonary venous return (PAPVR) Childhood and adolescence Growth failure, hearing defect, delayed puberty, skeletal abnor- malities Adulthood Secondary amenorrhea, infertility</p>\n<p><strong>Highyeild:</strong></p><p>Turner syndrome: Affected individuals have XO genotypes . Turner syndrome results from complete or partial monosomy of the X chromosome and is characterized by hypogonadism in phenotypic females . It is important to appreciate the karyotypic heterogeneity associated with Turner syndrome because it is responsible for significant variations in phenotype . In patients in whom the proportion of 45, X cells is high, the phenotypic changes are more severe than in those who have readily detectable mosaicism. The latter may have an almost normal appearance and may present only with primary amenorrhea. The classical presentation includes: Short stature Webbed neck Hypothyroidism, Insulin resistance Cubitus valgus Primary amenorrhea Streak ovaries Edema of the dorsum of the hand and foot due to lymph stasis and sometimes swelling of the nape of the neck . Congenital heart disease is also common, with left-sided cardiovascular abnormalities . In Turner syndrome, the most common cardiac anomaly seen is Bicuspid aortic valve>> Coarctation of the aorta . At puberty, there is a failure to develop normal secondary sex characteristics . The genitalia remains infantile , breast development is inadequate , and there is little pubic hair.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Coarctation of the aorta. 2nd most common cardiac defect with Turner . Option: C. Transposition of great arteries. Incorrect . Option: D. VSD. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>5-10% of patients with Turner syndrome have Y chromosome sequences either as a complete Y chromosome (e.g., 45, X/46, XY karyotype) or as fragments of Y chromosomes translocated on other chromosomes. These patients are at a higher risk for the development of a gonadal tumor (gonadoblastoma) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Analyze the given pedigree. Which disease is an example of this pattern?", "options": [{"label": "A", "text": "Alport syndrome", "correct": true}, {"label": "B", "text": "Marfan syndrome", "correct": false}, {"label": "C", "text": "Wilson disease", "correct": false}, {"label": "D", "text": "Tuberous sclerosis", "correct": false}], "correct_answer": "A. Alport syndrome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482561-QTDP036006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Alport syndrome Alport syndrome is caused by mutations affecting type IV collagen that result in hematuria with progression to chronic renal failure , accompanied by sensorineural deafness and various eye disorders, including lens dislocation, posterior cataracts, and corneal dystrophy .</p>\n<p><strong>Highyeild:</strong></p><p>X-linked disorders: This pedigree represents X linked dominant (XD) type of inheritance. Examples of XD: Alport syndrome Rett syndrome Fragile X syndrome Hypophosphatemic rickets (also called X-linked hypophosphatemia) Charcot-marie-tooth disease</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Marfan syndrome . It is an autosomal dominant type Option: C. Wilson disease. It is an autosomal recessive type Option: D. Tuberous sclerosis It is an autosomal dominant type</p>\n<p><strong>Table:</strong></p><p>Modes of inheritance: Autosomal Dominant: Autosomal Dominant Disorders System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von\n Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some\n variants)ª Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemia\n Acute intermittent porphyria Autosomal Recessive: Autosomal Recessive Disorders System Disorder Metabolic Cystic fibrosis Phenylketonuria Galactosemia Homocystinuria Lysosomal storage diseases α-Antitrypsin deficiency Wilson disease Hemochromatosis Glycogen storage diseases Hematopoietic Sickle cell anemia Thalassemias Endocrine Congenital adrenal hyperplasia Skeletal Ehlers-Danlos syndrome (some variants) Alkaptonuria Nervous Neurogenic muscular atrophies Friedreich ataxia Spinal muscular atrophy X Linked Recessive: X-Linked Recessive Disorders System Disease Musculoskeletal Duchenne muscular dystrophy Blood Hemophilia A and B Chronic granulomatous disease Glucose-6-phosphate\n dehydrogenase deficiency Immune Agammaglobulinemia Wiskott-Aldrich syndrome Metabolic Diabetes insipidus Lesch-Nyhan syndrome Nervous Fragile X syndrome X Linked Dominant: Alport syndrome Rett syndrome Fragile X syndrome Hypophosphatemic rickets (also called\n X-linked hypophosphatemia/ Vitamin D Resistant rickets) Charcot-marie-tooth disease Mitochondrial inheritance: Kearn Sayne Syndrome Leigh Syndrome MELAS MERRF NARP Leber Hereditary Optic Neuropathy Pearson Syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a pathology lecture professor shows an Image which is given below. This person looks more aged than he actually is. There is marked growth retardation. Lipodystrophy is present. Bilateral cataracts are seen. Premature greying of hair and hair loss are present. Infertility due to atrophy of gonads is seen. All are true, except:", "options": [{"label": "A", "text": "Diagnosis is Werner syndrome", "correct": false}, {"label": "B", "text": "The defective gene product is a DNA helicase", "correct": false}, {"label": "C", "text": "Autosomal Dominant inheritance is seen", "correct": true}, {"label": "D", "text": "There is an increased risk of cancer, especially Malignant melanoma", "correct": false}], "correct_answer": "C. Autosomal Dominant inheritance is seen", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482568-QTDP036008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Autosomal Dominant inheritance is seen The diagnosis is Werner syndrome . Patients with Werner syndrome show premature aging , and the defective gene product is a DNA helicase , a protein involved in DNA replication and repair and other functions requiring DNA unwinding. A defect in this enzyme causes rapid accumulation of chromosomal damage that may mimic some aspects of the injury that normally accumulates during cellular aging . Patients are at increased risk of cancers, mostly Malignant melanoma . Also known as \" adult progeria \" is a rare, autosomal recessive ( AR ) disorder.</p>\n<p><strong>Highyeild:</strong></p><p>Premature aging in Wer n er syndrome is d/t defect in D N A helicase. Bloom syndrome also shows defects in DNA helicase .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. The diagnosis is Werner syndrome. Correct . Option: B. The defective gene product is a DNA helicase. Correct . Option: D. There is an increased risk of cancer, especially Malignant melanoma. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>NOTE: Do not confuse with Wer M er syndrome which is seen in M EN-1.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A child has an abnormal palate, facial dimorphism, developmental delay, he has hypocalcemia. Diagnosis of DiGeorge syndrome is made. What chromosomal abnormality can be seen?", "options": [{"label": "A", "text": "Trisomy 21", "correct": false}, {"label": "B", "text": "22q11.2 deletion", "correct": true}, {"label": "C", "text": "Trisomy 18", "correct": false}, {"label": "D", "text": "Trisomy 13", "correct": false}], "correct_answer": "B. 22q11.2 deletion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>22q11.2 deletion DiGeorge syndrome is a T-cell deficiency that results from the failure of the development of the thymus . The third and fourth pharyngeal pouches , which give rise to the thymus, the parathyroids, some of the C cells of the thyroid, and the ultimobranchial body, do not develop normally . In the vast majority (90%) of cases, DiGeorge syndrome is caused by a small germline deletion that maps to chromosome 22q11, and DiGeorge syndrome is now considered a component of the 22q11 deletion syndrome . Chromosome 22q11.2 deletion syndrome encompasses a spectrum of disorders that result from a small deletion of band q11.2 on the long arm of chromosome 22 . Patients with DiGeorge syndrome have thymic hypoplasia , with resultant T-cell immunodeficiency , parathyroid hypoplasia giving rise to hypocalcemia , a variety of cardiac malformations affecting the outflow tract , and mild facial anomalies . Atopic disorders (e.g., allergic rhinitis) and autoimmunity (e.g., thrombocytopenia) may also be seen. The clinical features of the so-called velocardiofacial syndrome include facial dysmorphism (prominent nose, retrognathia), cleft palate, cardiovascular anomalies, and learning disabilities. Less frequently, these patients also have immunodeficiency.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Trisomy 21. Seen in Down syndrome . Option: C. Trisomy 18. Seen in Edward syndrome . Option: D. trisomy 13. Seen in Patau syndrome .</p>\n<p><strong>Extraedge:</strong></p><p>The most frequent forms of congenital heart disease in Down syndrome are atrioventricular septal defects . Cardiac problems are responsible for the majority of the deaths in infancy and early childhood. Several other congenital malformations, including atresias of the esophagus and small bowel , are also common. Children with trisomy 21 have a high risk of developing Leukemia ; there is a 20-fold increased risk of developing acute B lymphoblastic leukemias and a 500-fold increased risk of acute myeloid leukemias . The latter, most commonly, is acute megakaryoblastic leukemia (M7) . Almost all patients with trisomy 21 older than age 4 0 develop neuropathologic changes characteristic of Alzheimer's disease , a degenerative disorder of the brain. ( PYQ ) Patients with Down syndrome have abnormal immune responses that predispose them to serious infections , particularly of the lungs , and to thyroid autoimmunity .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true of the given pedigree except?", "options": [{"label": "A", "text": "Wilson's disease is an example", "correct": false}, {"label": "B", "text": "One parent should be affected", "correct": true}, {"label": "C", "text": "Causes disease only in the homozygous state of alleles", "correct": false}, {"label": "D", "text": "Most enzyme deficiency disorders follow this pattern", "correct": false}], "correct_answer": "B. One parent should be affected", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822482666-QTDP036010IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>One parent should be affected This pedigree is of autosomal recessive disorder . It is not necessary for parents to be affected . They can be carriers as well . Autosomal Recessive Disorders System Disorder Metabolic Cystic fibrosis Phenylketonuria Galactosemia Homocystinuria Lysosomal storage diseases α-Antitrypsin deficiency Wilson disease Hemochromatosis Glycogen storage diseases Hematopoietic Sickle cell anemia Thalassemias Endocrine Congenital adrenal hyperplasia Skeletal Ehlers-Danlos syndrome (some variants) Alkaptonuria Nervous Neurogenic muscular atrophies Friedreich ataxia Spinal muscular atrophy</p>\n<p><strong>Highyeild:</strong></p><p>Wilson disease: Wilson disease is an autosomal recessive disorder caused by a mutation of the ATP7B gene , resulting in impaired copper excretion into bile and a failure to incorporate copper into ceruloplasmin . This disorder is marked by the accumulation of toxic levels of copper in many tissues and organs, principally the liver, brain, and eye. Toxic brain injury primarily involves the basal ganglia . Nearly all patients with neurologic involvement develop eye lesions called Kayser-Fleischer rings , green to brown deposits of copper in the Descemet membrane in the limbus of the cornea. The biochemical diagnosis of Wilson disease is usually based on the presence of decreased serum ceruloplasmin, increased hepatic copper content (the most sensitive and accurate test), and increased urinary excretion of copper (the most specific test). Treatment: Early recognition and long-term copper chelation therapy (with D-penicillamine or trientine) or zinc-based therapy (which blocks the uptake of dietary copper in the gut) is effective. Individuals with hepatitis or unmanageable cirrhosis require liver transplantation, which can be curative.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Wilson's disease is an example. True , in Wilson's disease there's a mutation in the the ATP7B gene on Chromosome 13 . Excess copper accumulated in the liver, brain, and other vital organs . Option: C. Causes disease only in the homozygous state of alleles. Autosomal recessive traits are transmitted to both sexes and both males and females can be carriers. Because the gene is recessive, affected persons (who are homozygous for the gene) typically have parents and offspring who are unaffected ( heterozygous ) carriers . Option: D. Most enzyme deficiency disorders follow this pattern. True , many enzyme deficiency disorders follow an autosomal recessive pattern .</p>\n<p><strong>Table:</strong></p><p>Modes of inheritance: Autosomal Dominant: Autosomal Dominant Disorders System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some variants)ª Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemia Acute intermittent porphyria</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "In the dating of endometrium presence of secretory vacuoles beneath the nuclei of glandular epithelium denotes:", "options": [{"label": "A", "text": "Proliferate phase", "correct": false}, {"label": "B", "text": "Secretory phase", "correct": true}, {"label": "C", "text": "Menstrual phase", "correct": false}, {"label": "D", "text": "Infection", "correct": false}], "correct_answer": "B. Secretory phase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Secretory phase The presence of secretory vacuoles beneath the nuclei of glandular epithelium in the dating of endometrium denotes the Secretory phase. During the secretory phase of the menstrual cycle, the endometrium undergoes changes in preparation for the potential implantation of a fertilized egg. These changes are primarily driven by the hormone progesterone, which is secreted by the corpus luteum in the ovary after ovulation.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Proliferative phase: This phase of the endometrial cycle occurs prior to the secretory phase. During the proliferative phase, the endometrium thickens and the glandular epithelium proliferates in response to estrogen stimulation. Option: C. Menstrual phase: This phase marks the shedding of the endometrium when implantation does not occur. During this phase, the endometrial tissue is being shed and there is a lack of glandular development. Option: D. Infection: The presence of secretory vacuoles beneath the nuclei of glandular epithelium in the endometrial dating does not denote an infection. Infection would involve the infiltration of pathogens or inflammatory cells, and it would be characterized by signs of inflammation, such as immune cell infiltration and tissue damage</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most favoured site of endometriosis is:", "options": [{"label": "A", "text": "Uterine ligament", "correct": false}, {"label": "B", "text": "Ovary", "correct": true}, {"label": "C", "text": "Rectovaginal septum", "correct": false}, {"label": "D", "text": "Small intestine", "correct": false}], "correct_answer": "B. Ovary", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ovary The most favoured site of endometriosis is Ovary. Endometriosis commonly affects the ovaries, and the presence of endometrial tissue outside the uterus can lead to the f ormation of cysts called endometriomas on the ovaries. These cysts can cause pain, inflammation, and fertility issues.</p>\n<p><strong>Highyeild:</strong></p><p>Endometriosis Endometrium-like glands outside the endometrial cavity Most common site: Ovary Cause : This may be due to Retrograde menstruation, Metaplastic transformation of multipotent cells Transportation of endometrial tissue via the lymphatic system Features : pelvic pain Abnormal uterine bleeding Infertility Normal sized uterus Treatment: NSAIDs, OCPs, progestins, laparoscopic removal</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Uterine ligament: While endometriosis can affect the uterine ligaments, it is not the most favoured site. The uterine ligaments, including the broad ligaments, round ligaments, and uterosacral ligaments, can be involved in endometriosis, but they are not as commonly affected as the ovaries. Option: C. Rectovaginal septum: The rectovaginal septum is a common site for endometriosis. But ovaries are the most favoured. Option: D. Small intestine: While endometriosis can affect the digestive system and involve organs like the small intestine, it is less commonly seen compared to its prevalence in the pelvic region. The small intestine is not the most favoured site for endometriosis.</p>\n<p><strong>Extraedge:</strong></p><p>Endometriosis occurs in the following sites, in descending order of frequency: Ovaries, Uterine ligaments, rectovaginal septum, Cul de sac, Pelvic peritoneum, Large and small bowel and appendix, Mucosa of the cervix, vagina, and fallopian tubes, and laparotomy scars.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Endometriosis is defined by the presence of ectopic endometrial tissue at a site outside of the uterus, the word tissue denotes:", "options": [{"label": "A", "text": "Endometrial glands", "correct": false}, {"label": "B", "text": "Endometrial stroma", "correct": false}, {"label": "C", "text": "Macrophages with or without hemosiderin", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Endometriosis is characterized by the presence of ectopic endometrial tissue, which includes endometrial glands, endometrial stroma, and other components.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Inactivation of which tumour suppressor gene is associated with endometrial hyperplasia and endometrial carcinoma:", "options": [{"label": "A", "text": "TP 53", "correct": false}, {"label": "B", "text": "PTEN", "correct": true}, {"label": "C", "text": "WT1", "correct": false}, {"label": "D", "text": "PIK3CA", "correct": false}], "correct_answer": "B. PTEN", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PTEN Inactivation of the PTEN tumour suppressor gene is a common genetic alteration in both endometrial hyperplasias and endometrial carcinomas. PTEN acts as a negative regulator of the PI3K/AKT signalling pathway, which is involved in cell growth, proliferation, and survival. Loss of PTEN function leads to increased activation of the PI3K/AKT pathway, promoting cell proliferation and survival and contributing to the development of endometrial hyperplasia and carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. TP53: It is associated with a wide range of cancers but not specifically endometrial hyperplasia and carcinoma. Option: C. WT1: It is primarily associated with Wilms tumour and other genitourinary malignancies, not endometrial hyperplasia and carcinoma. Option: D. PIK3CA: It is a frequently mutated gene in various cancers, including some endometrial carcinomas, but it is not specifically associated with endometrial hyperplasia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding type I endometrial carcinoma except:", "options": [{"label": "A", "text": "Precursor lesion is endometrial hyperplasia", "correct": false}, {"label": "B", "text": "Histological type is serous or clear cell", "correct": true}, {"label": "C", "text": "Most commonly mutated gene is PTEN", "correct": false}, {"label": "D", "text": "It has indolent nature and spread via lymphatics", "correct": false}], "correct_answer": "B. Histological type is serous or clear cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Histological type is serous or clear cell The histological type of type I endometrial carcinoma is not a serous or clear cell. It is typically endometrioid carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Types I Endometrial Carcinoma These are the most common type, accounting for approximately 80% of cases. Genetic factors: PTEN mutation, MSI They typically arise in the setting of endometrial hyperplasia. They have indolent courses and spread via lymphatics. Histologic subtypes: Endometrioid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., C., D: All are true with respect to type 1 endometrial carcinoma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following Option:s are true regarding type II endometrial carcinoma ? Serous or clear cell histology PTEN or KRAS mutation Low-grade tumour Arises in an atrophic endometrium Estrogen dependent Select the correct answer from the given below code:", "options": [{"label": "A", "text": "1,3,4 correct", "correct": false}, {"label": "B", "text": "1,4 correct", "correct": true}, {"label": "C", "text": "2,3,5 correct", "correct": false}, {"label": "D", "text": "3,5 correct", "correct": false}], "correct_answer": "B. 1,4 correct", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>1,4 correct Type II Carcinoma generally occur in women who are about 10 years older than those with type I carcinomas, Arise in the setting of endometrial atrophy. Type II tumours are by definition poorly differentiated (grade 3) tumours and account for approximately 15% of cases of endometrial carcinoma. Types: Serous or clear cell histology</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most common gene mutated in serous endometrial carcinoma is-", "options": [{"label": "A", "text": "PTEN", "correct": false}, {"label": "B", "text": "WT1", "correct": false}, {"label": "C", "text": "TP53", "correct": true}, {"label": "D", "text": "CHD4", "correct": false}], "correct_answer": "C. TP53", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TP53 Serous endometrial carcinoma is a high-grade type of endometrial carcinoma , and TP53 mutations are frequently observed in this subtype. TP53 is a tumour suppressor gene that plays a crucial role in regulating cell cycle progression and DNA repair. Mutations in TP53 can lead to uncontrolled cell growth and tumour development.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. PTEN: It is another commonly mutated gene in endometrial cancer, but it is more frequently associated with the endometrioid subtype. Option: B. WT1: It is a gene that is involved in the development of various organs, but it is not typically associated with serous endometrial carcinoma. Option: D. CHD4: It (chromodomain helicase DNA-binding protein 4) is involved in chromatin remodelling, but it is not a commonly mutated gene in serous endometrial carcinoma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 58-year-old female presented with histologically proven endometrial hyperplasia 2 years back. At present, she has complaints of excessive bleeding PV and a CT scan shows a mass lesion in the uterus. The endometrial biopsy was taken and diagram of which is shown below. Based on histological features, Identify the type of tumour:", "options": [{"label": "A", "text": "Serous endometrial carcinoma", "correct": false}, {"label": "B", "text": "Endometrioid carcinoma", "correct": true}, {"label": "C", "text": "Clear cell carcinoma", "correct": false}, {"label": "D", "text": "Malignant mixed müllerian tumor", "correct": false}], "correct_answer": "B. Endometrioid carcinoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Endometrioid carcinoma The given clinical scenario with a histopathological image showing glandular growth patterns resembling normal endometrial epithelium is characteristic of endometrioid carcinoma. It is typically composed of well-formed glands with variable degrees of cytological atypia and architectural complexity.</p>\n<p><strong>Highyeild:</strong></p><p>Histological types of Endometrioid carcinoma Histological types Features Endometrioid ● The most common histological type of endometrial cancer ● Resembles the normal endometrium ● Typically associated with estrogen excess or hormonal imbalances ● Usually diagnosed at an early stage and has a relatively good prognosis Adenosquamous ● -A rare subtype of endometrial cancer ● Contains both glandular (adenocarcinoma) and squamous components ● Can be more aggressive and have Papillary Serous ● A high-grade, aggressive subtype of endometrial cancer ● Composed of papillary structures with atypical cells ● Typically not associated with estrogen exposure or hormonal imbalances ● Tends to be diagnosed at an advanced stage and has a worse prognosis Clear Cell ● A rare subtype of endometrial cancer characterized by clear cytoplasm ● Cells appear clear due to accumulation of glycogen or lipid within the cytoplasm ● Associated with a higher risk of recurrence and poorer prognosis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Serous endometrial carcinoma: It is a high-grade malignancy with a different histological appearance, characterized by papillary structures and marked cytological atypia. Option: C. Clear cell carcinoma: It is characterized by the presence of clear cytoplasm and has distinct histological features. Option: D. Malignant mixed Müllerian tumour: It (carcinosarcoma) is a biphasic tumour composed of both malignant epithelial and mesenchymal components, which is not consistent with the described histological features in the diagram.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Endometrial biopsy of a 65-year-old female patient showing malignant epithelial and mesenchymal elements as shown in the diagram, based on the histological findings, identify the type of tumour.", "options": [{"label": "A", "text": "Squamous cell carcinoma", "correct": false}, {"label": "B", "text": "Adenosquamous carcinoma", "correct": false}, {"label": "C", "text": "Malignant mixed müllerian tumor", "correct": true}, {"label": "D", "text": "Rhabdomyosarcoma", "correct": false}], "correct_answer": "C. Malignant mixed müllerian tumor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Malignant mixed müllerian tumor The given clinical scenario with the histopathological image showing the presence of malignant epithelial and mesenchymal components is suggestive of a Malignant mixed müllerian tumour.</p>\n<p><strong>Highyeild:</strong></p><p>Histological features of Malignant mixed Müllerian tumour (MMMT) It is a rare and aggressive malignancy that arises from the endometrium. Aka carcinosarcoma Presence of both malignant epithelial and mesenchymal components The epithelial component often shows papillary or glandular growth patterns , with cytological atypia and pleomorphism The mesenchymal component can include various types of sarcomas, such as leiomyosarcoma, chondrosarcoma, and osteosarcoma Tumour cells can invade the myometrium and adjacent structures , including the cervix, ovaries, and lymph nodes Mitotic activity and necrosis are frequently present Immunohistochemical stains can be used to differentiate between the epithelial and mesenchymal components of the tumour</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Squamous cell carcinoma: This is a type of cancer that arises from squamous cells, which are flat, scale-like cells that make up the outer layer of the skin and the lining of some organs. Squamous cell carcinoma of the endometrium is very rare and is usually associated with a history of pelvic irradiation. Option: B. Adenosquamous carcinoma: This is a rare type of endometrial cancer that contains both glandular (adenocarcinoma) and squamous (squamous cell carcinoma) components. It is typically more aggressive than endometrioid carcinoma, the most common type of endometrial cancer. Option: D. Rhabdomyosarcoma: This is a type of cancer that arises from skeletal muscle cells. It is extremely rare in the endometrium.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following cytogenetic abnormality seen in leiomyoma?", "options": [{"label": "A", "text": "Rearrangement of HMGIC gene", "correct": false}, {"label": "B", "text": "Rearrangement of HMGIY gene", "correct": false}, {"label": "C", "text": "Mutation of MED12 gene", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Leiomyomas are benign smooth muscle tumours that commonly occur in the uterus and are the most common tumours of the female genital tract. These tumours have been shown to have cytogenetic abnormalities involving rearrangements of the high mobility group proteins HMGIC and HMGIY, as well as mutations in the MED12 gene.</p>\n<p><strong>Highyeild:</strong></p><p>Leiomymoma Most common tumour in female Benign smooth muscle tumour Estrogen sensitive Increase size with pregnancy and decreased size in menopause Age: 20-40 years Symptoms: asymptomatic, abnormal uterine bleeding, iron deficiency anaemia Histology: Whorled pattern of smooth muscle bundles with well-demarcated borders</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most common site of metastasis in gestational choriocarcinoma?", "options": [{"label": "A", "text": "Liver", "correct": false}, {"label": "B", "text": "Breast", "correct": false}, {"label": "C", "text": "Lungs", "correct": true}, {"label": "D", "text": "Ovary", "correct": false}], "correct_answer": "C. Lungs", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lungs The most common site of metastasis in gestational choriocarcinoma is the lungs . Choriocarcinoma is a malignant tumour that arises from the trophoblastic cells of the placenta.</p>\n<p><strong>Highyeild:</strong></p><p>Choriocarcinoma It is a rare and aggressive form of gestational trophoblastic neoplasia (GTN) that arises from abnormal placental tissue. Elevated hCG Levels Can cause irregular or heavy vaginal bleeding Metastasis: Hematogenous spread Sites of metastasis: Commonly occurs in the lungs, liver, brain, and other distant sites Histological Features: Choriocarcinoma is characterized by the presence of syncytiotrophoblasts and cytotrophoblasts.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 41-year-old female patient presented with excessive bleeding during the menstrual period and increased urinary frequency. After hysterectomy, the histopathology shown in the diagram, identify the lesion based on its characteristic findings.", "options": [{"label": "A", "text": "Leiomyoma", "correct": true}, {"label": "B", "text": "Leiomyosarcoma", "correct": false}, {"label": "C", "text": "Angiosarcoma", "correct": false}, {"label": "D", "text": "Serous tumour", "correct": false}], "correct_answer": "A. Leiomyoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686835138451-QTDP155014IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leiomyoma The given clinical scenario and a histopathological image showing bundles of smooth muscle cells with well-defined borders and minimal cytological atypia suggests the diagnosis of Leiomyoma</p>\n<p><strong>Highyeild:</strong></p><p>Leiomymoma Most common tumour in female Benign smooth muscle tumour Estrogen sensitive Increase size with pregnancy and decreased size in menopause Age: 20-40 years Symptoms: asymptomatic, abnormal uterine bleeding, iron deficiency anaemia Histology: Whorled pattern of smooth muscle bundles with well-demarcated borders</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Leiomyosarcoma: Unlike leiomyomas, leiomyosarcomas have a high degree of cellularity, marked nuclear pleomorphism, and atypical mitoses. They are also more invasive and have a higher risk of metastasis. Option: C. Angiosarcoma: Angiosarcomas are malignant vascular tumours and usually present as skin lesions. They are characterized by anastomosing channels lined by atypical endothelial cells, which is not seen in the provided image. Option: D. Serous tumour: Serous tumours usually arise from the ovary and rarely involve the uterus. They are characterized by papillary projections lined by cuboidal to columnar cells with clear cytoplasm, which is not seen in the provided image.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 22 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "For all of the following mentioned diseases, the bronchus is the site of pathological changes except:", "options": [{"label": "A", "text": "Chronic bronchitis", "correct": false}, {"label": "B", "text": "Asthma", "correct": false}, {"label": "C", "text": "Bronchiectasis", "correct": false}, {"label": "D", "text": "Emphysema", "correct": true}], "correct_answer": "D. Emphysema", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Emphysema Emphysema occurs at the site of the acinus , rest of all occurs at the site of the bronchus</p>\n<p><strong>Highyeild:</strong></p><p>Emphysema Emphysema is a lung disease characterized by the destruction of the alveoli (air sacs) in the lungs , leading to shortness of breath and difficulty breathing. -Risk factors: The most significant risk factor for Emphysema is cigarette smoking Alpha-1 antitrypsin deficiency Long-term exposure to air pollution and occupational exposure to dust, fumes, and chemicals. -Pathophysiology: -Features: Chronic shortness of breath, chronic cough with scanty sputum production , and reduced exercise tolerance. Wheezing, chest tightness, and weight loss. Barrel-shaped chest Expiration is prolonged and/or through pursed lips Diagnostic tests: Pulmonary function tests: Decreased FEV1/FVC ratio, decreased DLCO, and increased residual volume. Chest X-rays may show hyperinflation of the lungs with flattened diaphragms: Increased lung field lucency</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., C: Chronic bronchitis, Asthma, and Bronchiectasis: All involve inflammation and damage to the bronchial tubes, leading to symptoms such as coughing, wheezing, and shortness of breath.</p>\n<p><strong>Extraedge:</strong></p><p>Emphysema Vs Chronic Bronchitis Emphysema Chronic Bronchitis Aka Pink puffers Blue bloaters Presentation Shortness of breath and scanty sputum production Chronic productive cough General Appearance Thin, sometimes cachexic, with rosy skin tones Often overweight, obese Sputum Scanty , Mucoid Copious , Purulent Cor Pulomonale Rare, except in the late stages More prominent Chest X-ray findings Hyperinflated lungs , small heart. Diaphragm: low and flat Normal-sized lungs, Right ventricular hypertrophy. Normal shaped diaphragm Other findings Barrel chest Cyanotic, Peripheral edema Pulmonary function tests Decreased FEV1/FVC ratio, decreased DLCO , increased residual volume Decreased FEV1/FVC ratio, normal or slightly decreased DLCO, normal or increased residual volume</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true with respect to centriacinar emphysema? Most common type of emphysema Distal alveoli are spared It is associated with Alpha-1 antitrypsin deficiency It is common and more severe in the lower lobe It is commonly seen in smokers Select the correct answer from given below code:", "options": [{"label": "A", "text": "1,2,3,5 correct", "correct": false}, {"label": "B", "text": "1,3,5 correct", "correct": false}, {"label": "C", "text": "1,2,5 correct", "correct": true}, {"label": "D", "text": "1,2,3,4,5 correct", "correct": false}], "correct_answer": "C. 1,2,5 correct", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>1,2,5 correct Centriacinar emphysema The central or proximal parts of the acini, formed by respiratory bronchioles, are affected Distal alveoli are spared . Thus, both emphysematous and normal airspaces exist within the same acinus and lobule. The lesions are more common and usually more severe in the upper lobes , particularly in the apical segments. Centriacinar emphysema occurs predominantly in heavy smokers , often in association with chronic bronchitis (COPD).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Statement 3. Alpha-1-antitrypsin is often associated with Panacinar emphysema. Statement 4. Lower lobes are commonly affected in Panacinar emphysema.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 65-year-old male presents to the clinic with complaints of chronic shortness of breath. The patient reports a history of smoking for over 40 years. On examination, the patient has reduced breath sounds and wheezing on auscultation. Pulmonary function tests show decreased FEV1/FVC ratio and decreased DLCO. A chest X-ray shows hyperinflation of the lungs with flattened diaphragms. Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Chronic bronchitis", "correct": false}, {"label": "B", "text": "Asthma", "correct": false}, {"label": "C", "text": "Bronchiectasis", "correct": false}, {"label": "D", "text": "Emphysema", "correct": true}], "correct_answer": "D. Emphysema", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Emphysema The given clinical scenario is suggestive of Emphysema. The patient's history of smoking, chronic shortness of breath , reduced breath sounds, and wheezing on auscultation are all suggestive of Emphysema. Pulmonary function tests show decreased FEV1/FVC ratio and decreased DLCO, which are characteristic of Emphysema.</p>\n<p><strong>Highyeild:</strong></p><p>Emphysema Emphysema is a lung disease characterized by the destruction of the alveoli (air sacs) in the lungs , leading to shortness of breath and difficulty breathing. -Risk factors: The most significant risk factor for Emphysema is cigarette smoking Alpha-1 antitrypsin deficiency Long-term exposure to air pollution and occupational exposure to dust, fumes, and chemicals. -Pathophysiology: -Features: Chronic shortness of breath, chronic cough with scanty sputum production , and reduced exercise tolerance. Wheezing, chest tightness, and weight loss. Barrel-shaped chest Expiration is prolonged and/or through pursed lips Diagnostic tests: Pulmonary function tests: Decreased FEV1/FVC ratio, decreased DLCO, and increased residual volume. Chest X-rays may show hyperinflation of the lungs with flattened diaphragms: Increased lung field lucency</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Chronic bronchitis: It is characterized by cough and sputum production for at least three months in each of two consecutive years, but it does not typically cause wheezing or reduced breath sounds on auscultation. In addition, pulmonary function tests in chronic bronchitis usually show normal or only slightly decreased DLCO. Option: B. Asthma : It is a chronic inflammatory disease of the airways that causes recurrent episodes of wheezing, breathlessness, chest tightness, and coughing. A smoking history is not typical of asthma. Additionally, the pulmonary function tests and chest X-ray findings, in this case, are not consistent with asthma. Option: C. Bronchiectasis : It is a chronic lung disease characterized by permanent dilation and thickening of the bronchial walls, which can lead to chronic cough, sputum production, and recurrent respiratory infections. X-ray findings are not typical of this condition. Pulmonary function tests in bronchiectasis may show obstructive or restrictive patterns, but the decreased DLCO, in this case, is not typical of bronchiectasis.</p>\n<p><strong>Extraedge:</strong></p><p>Emphysema Vs Chronic Bronchitis Emphysema Chronic Bronchitis Aka Pink puffers Blue bloaters Presentation Shortness of breath and scanty sputum production Chronic productive cough General appearance Thin, sometimes cachexic, with rosy skin tones Often overweight, obese Sputum Scanty , Mucoid Copious , Purulent Cor Pulomonale Rare, except in the late stages More prominent Chest X-ray findings Hyperinflated lungs , small heart. Diaphragm: low and flat Normal-sized lungs, Right ventricular hypertrophy. Normal shaped diaphragm Other findings Barrel chest Cyanotic, Peripheral edema Pulmonary function tests Decreased FEV1/FVC ratio, decreased DLCO , increased residual volume Decreased FEV1/FVC ratio, normal or slightly decreased DLCO, normal or increased residual volume</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the mouse model, which gene is associated with smoking-related lung disease in humans?", "options": [{"label": "A", "text": "NRF 2", "correct": true}, {"label": "B", "text": "ABCA 3", "correct": false}, {"label": "C", "text": "MyD88", "correct": false}, {"label": "D", "text": "NRTK 1", "correct": false}], "correct_answer": "A. NRF 2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NRF 2 NRF2 is a transcription factor that plays a key role in the body's response to oxidative stress and inflammation. In a mouse model of smoking-induced lung disease, it has been shown that the loss of NRF2 function leads to increased susceptibility to emphysema and other smoking-related lung diseases. This finding has been supported by studies in humans, which have shown that NRF2 expression is decreased in the lungs of smokers with COPD. Therefore, NRF2 is a potential therapeutic target for smoking-related lung diseases in humans.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. ABCA3: It is a gene that is involved in the metabolism of surfactant in the lungs and mutations in this gene can lead to pulmonary surfactant metabolism dysfunction, a rare genetic disease. Option: C. MyD88 is a gene that is involved in the innate immune system and has been implicated in a variety of inflammatory and infectious diseases. Option: D. NRTK1: It (aka Tyro3) is a gene that is involved in cell signaling pathways and has been implicated in various cellular processes, including immune regulation and cell survival. It has been studied in the context of lung cancer and other cancers.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Proteinase inhibitors (pi) which code for alpha1 antitrypsin are located on which chromosome?", "options": [{"label": "A", "text": "10", "correct": false}, {"label": "B", "text": "12", "correct": false}, {"label": "C", "text": "14", "correct": true}, {"label": "D", "text": "17", "correct": false}], "correct_answer": "C. 14", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>14 α1-antitrypsin is encoded by the proteinase inhibitor (Pi) locus on chromosome 14 . About 1% of all patients with emphysema have this defect. α1-antitrypsin, normally present in serum, tissue fluids, and macrophages, is a major inhibitor of proteases (particularly elastase) secreted by neutrophils during inflammation.</p>\n<p><strong>Highyeild:</strong></p><p>Emphysema Emphysema is a lung disease characterized by the destruction of the alveoli (air sacs) in the lungs , leading to shortness of breath and difficulty breathing. -Risk factors: The most significant risk factor for Emphysema is cigarette smoking Alpha-1 antitrypsin deficiency Long-term exposure to air pollution and occupational exposure to dust, fumes, and chemicals. -Pathophysiology: -Features: Chronic shortness of breath, chronic cough with scanty sputum production , and reduced exercise tolerance. Wheezing, chest tightness, and weight loss. Barrel-shaped chest Expiration is prolonged and/or through pursed lips Diagnostic tests: Pulmonary function tests: Decreased FEV1/FVC ratio, decreased DLCO, and increased residual volume. Chest X-rays may show hyperinflation of the lungs with flattened diaphragms: Increased lung field lucency</p>\n<p><strong>Extraedge:</strong></p><p>Emphysema Vs Chronic Bronchitis Emphysema Chronic Bronchitis Aka Pink puffers Blue bloaters Presentation Shortness of breath and scanty sputum production Chronic productive cough General appearance Thin, sometimes cachexic, with rosy skin tones Often overweight, obese Sputum Scanty , Mucoid Copious , Purulent Cor Pulomonale Rare, except in the late stages More prominent Chest X-ray findings Hyperinflated lungs , small heart. Diaphragm: low and flat Normal-sized lungs, Right ventricular hypertrophy. Normal shaped diaphragm Other findings Barrel chest Cyanotic, Peripheral edema Pulmonary function tests Decreased FEV1/FVC ratio, decreased DLCO , increased residual volume Decreased FEV1/FVC ratio, normal or slightly decreased DLCO, normal or increased residual volume</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding histological features of M5 emphysema except:", "options": [{"label": "A", "text": "There is a loss of attachments of the alveoli to the outer wall of small airways", "correct": false}, {"label": "B", "text": "The pores of Kohn Become narrower and obstructed", "correct": true}, {"label": "C", "text": "It causes a decrease in the capillary bed area", "correct": false}, {"label": "D", "text": "There is a large abnormal space as blebs and bullae", "correct": false}], "correct_answer": "B. The pores of Kohn Become narrower and obstructed", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The pores of Kohn Become narrower and obstructed M5 emphysema, also known as panlobular emphysema or panacinar emphysema , is a type of emphysema that affects the entire acinus, including the respiratory bronchioles, alveolar ducts, and alveoli. The pores of Kohn are small holes that connect adjacent alveoli, allowing collateral ventilation to occur. In M5 emphysema , the destruction of alveolar walls results in the enlargement of air spaces, including the pores of Kohn , rather than narrowing and obstruction. Histological features of M5/panacinar Emphysema</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option A:- There is a loss of attachments of the alveoli to the outer wall of small airways, which results in the collapse of small airways during expiration. Option C:- It causes a decrease in capillary bed area due to the destruction of alveolar walls, which results in decreased oxygen exchange efficiency. Option D:- There is a large abnormal space as blebs and bullae due to the destruction of alveolar walls, which results in the formation of large air spaces.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Loss of function mutation of which gene is responsible for the majority of cases of Hirschsprung's disease:", "options": [{"label": "A", "text": "WT 1", "correct": false}, {"label": "B", "text": "MET", "correct": false}, {"label": "C", "text": "RET", "correct": true}, {"label": "D", "text": "PTEN", "correct": false}], "correct_answer": "C. RET", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RET The loss of function mutation of the RET gene is responsible for the majority of cases of Hirschsprung's disease. RET is a proto-oncogene that plays a crucial role in the development of the enteric nervous system , which controls the motility of the gastrointestinal tract. Mutations in RET can lead to abnormal migration or differentiation of the ENS precursor cells during fetal development, resulting in the absence or reduction of ganglion cells in the distal colon and rectum. This leads to a functional obstruction of the affected bowel segment, causing symptoms such as constipation, abdominal distension, and vomiting.</p>\n<p><strong>Highyeild:</strong></p><p>Hirschsprung disease Aka congenital aganglionic megacolon Autosomal dominant inheritance More common in males than females Cause: Loss of function mutation of the RET gene leading to failure of migration of neural crest cells during embryonic development, resulting in an absence of ganglion cells in the distal colon. Features: Failure to pass meconium within 24-48 hours after birth, Abdominal distention, vomiting, and constipation. Diagnosis: Rectal biopsy shows the absence of ganglion cells in the affected segment of the colon Treatment: Surgery</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. WT1: (Wilms tumour 1) It is a tumour suppressor gene that is involved in the development of the kidneys and gonads, and mutations in this gene are associated with Wilms tumour and some forms of gonadal cancer. Option: B. MET: It is a proto-oncogene that encodes a receptor tyrosine kinase involved in cell proliferation, survival, and migration. Not associated with Hirschsprung disease. Option: D. PTEN: It is a tumour suppressor gene. Mutations in PTEN have been implicated in several inherited syndromes, including Cowden syndrome not associated with hirschsprung disease.</p>\n<p><strong>Table:</strong></p><p>Findings in Hirschsprung disease Histopathological findings (Rectal biopsy) Absence of ganglion cells in the affected\n segment of the bowel Presence of hypertrophic nerve trunks in the\n submucosal and myenteric plexuses Dilatation of the colon proximal to the\n aganglionic segment Focal inflammation in the aganglionic\n segment Contrast enema Shows a narrow distal segment Funnel-shaped dilatation at the level of the transition\n zone Marked dilatation of the proximal colon Rectal manometry Absence of the recto anal inhibitory reflex\n when the rectum is distended</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which statement regarding Hirschsprung's disease is false?", "options": [{"label": "A", "text": "Occurs due to the absence of neural crest cell migration", "correct": false}, {"label": "B", "text": "Absence of ganglion cells in the affected segment", "correct": false}, {"label": "C", "text": "Rectum is always spared", "correct": true}, {"label": "D", "text": "Intraoperative frozen section done to confirm the diagnosis", "correct": false}], "correct_answer": "C. Rectum is always spared", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rectum is always spared Hirschsprung disease results when the normal migration of neural crest cells from the cecum to the rectum is arrested prematurely or when the ganglion cells undergo premature death. The rectum can be involved in Hirschsprung's disease , depending on the extent of aganglionosis.</p>\n<p><strong>Highyeild:</strong></p><p>Hirschsprung disease Aka congenital aganglionic megacolon Autosomal dominant inheritance More common in males than females Cause: Loss of function mutation of the RET gene leading to failure of migration of neural crest cells during embryonic development, resulting in an absence of ganglion cells in the distal colon. Features: Failure to pass meconium within 24-48 hours after birth, Abdominal distention, vomiting, and constipation. Diagnosis: Rectal biopsy shows the absence of ganglion cells in the affected segment of the colon Treatment: Surgery</p>\n<p><strong>Table:</strong></p><p>Findings in Hirschsprung disease Histopathological findings (Rectal biopsy) Absence of ganglion cells in the affected segment of the bowel Presence of hypertrophic nerve trunks in the submucosal and myenteric plexuses Dilatation of the colon proximal to the aganglionic segment Focal inflammation in the aganglionic segment Contrast enema Shows a narrow distal segment Funnel-shaped dilatation at the level of the transition zone Marked dilatation of the proximal colon Rectal manometry Absence of the recto anal inhibitory reflex when the rectum is distended</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a histological feature commonly seen in Barrett's esophagus?", "options": [{"label": "A", "text": "Squamous epithelium with basal cell hyperplasia", "correct": false}, {"label": "B", "text": "Columnar epithelium with goblet cells", "correct": true}, {"label": "C", "text": "Dysplastic epithelium with atypical cells", "correct": false}, {"label": "D", "text": "Fibrous tissue with chronic inflammation", "correct": false}], "correct_answer": "B. Columnar epithelium with goblet cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Columnar epithelium with goblet cells Barrett's esophagus is a complication of chronic GERD that is characterized by intestinal metaplasia within the esophageal squamous mucosa. There is the replacement of the normal squamous epithelium of the esophagus with a columnar epithelium containing goblet cells.</p>\n<p><strong>Highyeild:</strong></p><p>Barrett’s esophagus It refers to an abnormal change in the cells of the lower portion of the esophagus . Cause: Chronic acid exposure from reflux esophagitis- GERD Symptoms: Frequent and long-standing heartburn, dysphagia, hematemesis Histopathology :</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Squamous epithelium with basal cell hyperplasia: It is a feature commonly seen in squamous cell carcinoma of the esophagus, not in Barrett's esophagus. Option: C. Dysplastic epithelium with atypical cells: It is a feature seen in high-grade dysplasia or adenocarcinoma, which can develop in patients with long-standing Barrett's esophagus. Option: D. Fibrous tissue with chronic inflammation: It is a nonspecific finding that can be seen in many types of chronic inflammation, including reflux esophagitis but it is not a specific feature of Barrett's esophagus.</p>\n<p><strong>Extraedge:</strong></p><p>Screening of Barrett’s esophagus: Proposed surveillance and management algorithm for patients with Barrett's esophagus based on the grade of dysplasia detected by endoscopy with biopsies. Low-grade dysplasia arm assumes that a follow-up endoscopy with biopsy has been performed to exclude concomitant cancer. High-grade dysplasia arm assumes confirmation of diagnosis by expert pathologist.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding histological features of Barrett's esophagus except:", "options": [{"label": "A", "text": "Intestinal metaplasia occurs", "correct": false}, {"label": "B", "text": "Sub-Classified based on length of involvement", "correct": false}, {"label": "C", "text": "Increases risk of adenocarcinoma", "correct": false}, {"label": "D", "text": "Dysplastic cells invade the lamina propria", "correct": true}], "correct_answer": "D. Dysplastic cells invade the lamina propria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dysplastic cells invade the lamina propria Dysplasia is a premalignant change that can be seen in the epithelium of Barrett's esophagus, but dysplastic cells do not invade the lamina propria.</p>\n<p><strong>Highyeild:</strong></p><p>Barrett’s esophagus It refers to an abnormal change in the cells of the lower portion of the esophagus . Cause: Chronic acid exposure from reflux esophagitis- GERD Symptoms: Frequent and long-standing heartburn, dysphagia, hematemesis Histopathology :</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Intestinal metaplasia occurs: It is true. The columnar epithelium with goblet cells seen in Barrett's esophagus represents intestinal metaplasia, which is the replacement of the normal stratified squamous epithelium by specialized columnar epithelium. Option: B. Sub-Classified based on length of involvement: It is true. Barrett's esophagus is classified into short segment (i.e. extends up to 3 cm from the GE junction) and long segment (i.e. extends beyond 3 cm) Option: C. Increases risk of adenocarcinoma: It is true. The risk of adenocarcinoma is directly proportional to the length of the involved segment of the esophagus.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which special stain is performed to confirm the diagnosis of Barrett's esophagus:", "options": [{"label": "A", "text": "AB-PAS", "correct": true}, {"label": "B", "text": "PAS", "correct": false}, {"label": "C", "text": "SM", "correct": false}, {"label": "D", "text": "CV", "correct": false}], "correct_answer": "A. AB-PAS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>AB-PAS ABPAS (Alcian blue & PAS) is the most commonly used stain to identify the type of mucus secretion and confirmation of the histological diagnosis of Barrett's esophagus.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. PAS: (Periodic Acid-Schiff) It is also used to detect the presence of goblet cells, but AB-PAS is preferred as it stains the mucin produced by goblet cells more intensely. Option: C. SM Sternheimer-Malbin (SM) stain is a supravital stain. It's a stabilized mixture of crystal violet and safranin Used for sediment examination to reveal ova to assist in diagnosis of giant kidney and bladder worms. Leukocytes, epithelial cells, and casts stain well with this stain. Option: D. CV: (Crystal Violet) It is a general stain that is commonly used to visualize bacteria in tissue sections, such as in the evaluation of infectious agents in gastrointestinal infections.</p>\n<p><strong>Table:</strong></p><p>Commonly\n used pathological stains Stain Use Hematoxylin and Eosin (H&E) General staining of tissues, used to visualize cellular and tissue\n morphology Periodic Acid-Schiff (PAS) Carbohydrate-rich structures like glycogen, basement membranes, and\n fungal organisms Masson's trichrome Connective tissue, muscle, and collagen fibres Congo red Amyloidosis Ziehl-Neelsen Acid-fast organisms like Mycobacterium tuberculosis Wright-Giemsa Blood cells and bone marrow Prussian blue Iron deposition in tissues, as seen in hemochromatosis Alcian blue Acidic mucopolysaccharides, such as those found in intestinal goblet\n cells Toluidine blue Mast cells and their granules</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 50-year-old patient had repeated episodes of reflux and burning pain for a prolonged duration. An esophageal biopsy was performed and shown below. What is your diagnosis?", "options": [{"label": "A", "text": "Reflux esophagitis", "correct": false}, {"label": "B", "text": "Eosinophilic esophagitis", "correct": false}, {"label": "C", "text": "Viral esophagitis", "correct": false}, {"label": "D", "text": "Barrett esophagus", "correct": true}], "correct_answer": "D. Barrett esophagus", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157243628-QTDP112006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Barrett esophagus The given clinical history with the histopathological image is suggestive of intestinal metaplasia i.e. replacement of the squamous esophageal epithelium with goblet cells that points to the diagnosis of Barrett's esophagus.</p>\n<p><strong>Highyeild:</strong></p><p>Barrett’s esophagus It refers to an abnormal change in the cells of the lower portion of the esophagus . Cause: Chronic acid exposure from reflux esophagitis- GERD Symptoms: Frequent and long-standing heartburn, dysphagia, hematemesis Histopathology :</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Reflux esophagitis: It is characterized by inflammatory changes in the esophageal mucosa due to gastroesophageal reflux disease. Option: B. Eosinophilic esophagitis: It is characterized by eosinophilic inflammation of the esophageal mucosa. The histological features include a dense eosinophilic infiltrate with basal cell hyperplasia and elongation of the papillae. Option: C. Viral esophagitis: It can be caused by various viruses, such as herpes simplex virus, cytomegalovirus, and human papillomavirus, and is characterized by viral cytopathic changes in the esophageal epithelium.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is the most common benign tumour of esophagus?", "options": [{"label": "A", "text": "Fibroma", "correct": false}, {"label": "B", "text": "Leiomyoma", "correct": true}, {"label": "C", "text": "Hemangioma", "correct": false}, {"label": "D", "text": "Neurofibroma", "correct": false}], "correct_answer": "B. Leiomyoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leiomyoma Benign tumours of the esophagus are generally mesenchymal, and arise within the esophageal wall, with leiomyomas being the most common.</p>\n<p><strong>Highyeild:</strong></p><p>Esophageal Leiomyomas They are the most common benign tumour of the esophagus. Usually found incidentally in imaging studies or endoscopies. Symptoms may include dysphagia, chest pain, or reflux. They are more common in middle-aged women. They appear as well-defined submucosal masses on endoscopy. Treatment: Surgical resectio n for symptomatic or large leiomyomas, while smaller asymptomatic lesions may be monitored with periodic imaging.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fibroma: It is a rare benign tumour of the esophagus that is composed of fibrous tissue. Option: C. Hemangioma: It is another rare benign tumour of the esophagus that is composed of blood vessels. Option: D. Neurofibroma: It is a benign tumour of nerve tissue, and while it can occur in the esophagus, it is very rare.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding adenocarcinoma of esophagus except:", "options": [{"label": "A", "text": "Mostly arises from Barrett's esophagus", "correct": false}, {"label": "B", "text": "It occurs in the upper esophagus", "correct": true}, {"label": "C", "text": "Mutation of TP53 and p16/INK4a is seen", "correct": false}, {"label": "D", "text": "Tumor cell most commonly produces mucin and forms glands", "correct": false}], "correct_answer": "B. It occurs in the upper esophagus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It occurs in the upper esophagus Adenocarcinoma usually occurs in the lower esophagus or gastroesophageal junction, not in the upper esophagus. It is a type of cancer that typically arises from Barrett's esophagus, a condition in which the normal squamous epithelium of the lower esophagus is replaced by intestinal-type columnar epithelium. The tumour cells of adenocarcinoma often produce mucin and form glandular structures.</p>\n<p><strong>Highyeild:</strong></p><p>Adenocarcinoma of the esophagus Adenocarcinoma of the esophagus is typically characterized by glandular differentiation. Risk factors : Strongly associated with gastroesophageal reflux disease ( GERD ), which causes chronic inflammation of the esophagus. Chromosomal abnormalities, mutation of TP53 , and downregulation of the cyclin-dependent kinase inhibitor CDKN2A (aka p16/INK4a) are detected at early stages. The tumour cells may invade the lamina propria and the muscularis mucosae. Progression: This usually progresses from dysplastic changes in the overlying Barrett's esophagus HPE: Tumors most commonly produce mucin and form glands , often with intestinal-type morphology.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Mostly arises from Barrett's esophagus: Adenocarcinoma of the esophagus is most commonly associated with Barrett’s esophagus, which is a precancerous condition Option: C. Mutation of TP53 and p16/INK4a is seen: Adenocarcinoma of the esophagus is associated with genetic mutations, including alterations in the tumour suppressor genes TP53 and p16/INK4a. Option: D. Tumor cell most commonly produces mucin and form glands: Adenocarcinoma of the esophagus is characterized by glandular differentiation, which means that the tumour cells produce mucin and form gland-like structures.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following genetic mutations is commonly found in esophageal squamous cell carcinoma?", "options": [{"label": "A", "text": "KRAS", "correct": false}, {"label": "B", "text": "BRAF", "correct": false}, {"label": "C", "text": "TP53", "correct": true}, {"label": "D", "text": "EGFR", "correct": false}], "correct_answer": "C. TP53", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TP53 Esophageal squamous cell carcinoma is commonly associated with TP53 mutations. TP53 encodes the tumour suppressor protein p53, which plays a crucial role in cell cycle regulation, DNA repair, and apoptosis. Mutations in TP53 can lead to loss of p53 function, resulting in uncontrolled cell growth and tumorigenesis.</p>\n<p><strong>Highyeild:</strong></p><p>Squamous cell carcinoma (SCC) of the esophagus It is the most common type of esophageal cancer worldwide, accounting for approximately 90% of all cases. Risk factors: Smoking tobacco, excessive alcohol consumption, hot beverage consumption, and a diet lacking in fruits and vegetables. Cause: Amplification of the transcription factor gene SOX2 ; overexpression of the cell cycle regulator cyclin D1; and loss-of-function mutations in the tumour suppressors TP53, E-cadherin, and NOTCH1. Site: Typically arises from the middle third of the esophagus.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. KRAS: This gene is commonly mutated in various types of cancer, including pancreatic cancer, colorectal cancer, and lung cancer. But not related to esophageal squamous cell carcinoma. Option: B. BRAF: This gene is also commonly mutated in various types of cancer, including melanoma and colorectal cancer. Option: D. EGFR: Mutations in this gene are commonly found in non-small cell lung cancer and some other types of cancer.</p>\n<p><strong>Extraedge:</strong></p><p>HPE: SCC of the esophagus is characterized by malignant squamous cell s forming irregular nests, islands, or cords. The cells have a high nucleus-to-cytoplasm ratio and may have keratinization or intercellular bridges.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 55-year-old has a prolonged history of alcohol and tobacco chewing and presented with symptoms of dysphagia. A mass lesion was seen on the barium meal in the esophagus. Esophageal biopsy was taken and shown below, what is your diagnosis?", "options": [{"label": "A", "text": "Adenocarcinoma", "correct": false}, {"label": "B", "text": "Carcinoid tumour", "correct": false}, {"label": "C", "text": "Squamous cell carcinoma", "correct": true}, {"label": "D", "text": "Adenosquamous carcinoma", "correct": false}], "correct_answer": "C. Squamous cell carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157244944-QTDP112011IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Squamous cell carcinoma The given clinical scenario and a histopathological image showing keratin pearls are suggestive of Squamous cell carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Squamous cell carcinoma (SCC) of the esophagus It is the most common type of esophageal cancer worldwide, accounting for approximately 90% of all cases. Risk factors: Smoking tobacco, excessive alcohol consumption, hot beverage consumption, and a diet lacking in fruits and vegetables. Cause: Amplification of the transcription factor gene SOX2 ; overexpression of the cell cycle regulator cyclin D1; and loss-of-function mutations in the tumour suppressors TP53, E-cadherin, and NOTCH1. Site: Typically arises from the middle third of the esophagus.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Adenocarcinoma: It is more commonly associated with gastroesophageal reflux disease and Barrett's esophagus. Option: B. Carcinoid tumour: These are rare neuroendocrine tumours that can develop in various organs of the body, including the gastrointestinal tract, lungs, and liver. In the esophagus, carcinoid tumours are extremely rare. Option: D. Adenosquamous carcinoma: It is less likely because adenosquamous carcinoma is a rare type of esophageal cancer and may not present with keratin pearls on biopsy.</p>\n<p><strong>Extraedge:</strong></p><p>HPE: SCC of the esophagus is characterized by malignant squamous cell s forming irregular nests, islands, or cords. The cells have a high nucleus-to-cytoplasm ratio and may have keratinization or intercellular bridges.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In the case of gastric adenocarcinoma metastasis to the axilla is known as:", "options": [{"label": "A", "text": "Virchow node", "correct": false}, {"label": "B", "text": "Blumer shelf", "correct": false}, {"label": "C", "text": "Irish node", "correct": true}, {"label": "D", "text": "Sister Mary Joseph's nodule", "correct": false}], "correct_answer": "C. Irish node", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Irish node An Irish node is an enlarged axillary lymph node caused by metastasis, often associated with gastric adenocarcinoma .</p>\n<p><strong>Highyeild:</strong></p><p>Metastatic Gastric Cancer: Eponymous clinical signs</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Virchow node: Refers to the left supraclavicular lymph node, which is a common site for metastasis from gastric adenocarcinoma. Option: B. Blumer shelf: Metastasis in the pouch of Douglas. Option: D. Sister Mary Joseph nodule: Metastatic nodule that can be found in the umbilicus and is often associated with gastric adenocarcinoma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following proteins is associated with the development of diffuse gastric carcinoma?", "options": [{"label": "A", "text": "APC", "correct": false}, {"label": "B", "text": "β-catenin", "correct": false}, {"label": "C", "text": "E cadherin", "correct": true}, {"label": "D", "text": "TP 53", "correct": false}], "correct_answer": "C. E cadherin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>E cadherin E-cadherin is a calcium-dependent cell adhesion protein that plays an important role in maintaining the integrity of epithelial cell layers Loss of its expression is thought to promote the progression of cancer by disrupting the adhesion between cells. In diffuse gastric carcinoma, there is often a germline or somatic mutation in the CDH1 gene, which encodes for E-cadherin , leading to its loss of expression.</p>\n<p><strong>Highyeild:</strong></p><p>Diffuse Gastric Carcinoma Infiltrating gastric adenocarcinoma with diffuse infiltration of the gastric wall and little to no gland formation Age: Older adults, Males predominance Cause: CDH1 gene mutation Risk factors: Family history of gastric cancer, Helicobacter pylori infection, chronic gastritis, pernicious anaemia, smoking, high salt intake Symptoms: Early stages - Usually symptomatic, later stages- weight loss, dysphagia, nausea, vomiting, abdominal pain Histological features: Poorly cohesive cells , signet ring cells , mucin pools, desmoplastic reaction , often with absence of gland formation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. APC: Adenomatous polyposis coli (APC) gene mutations are associated with the development of colorectal cancer, not diffuse gastric carcinoma. Option: B. β-catenin: β-catenin is a protein involved in the Wnt signalling pathway and is often mutated in colon cancer. Option: D. TP53: TP53 is a tumo u r suppressor gene that is commonly mutated in many types of cancers.</p>\n<p><strong>Table:</strong></p><p>· Lauren ’s classification of Gastric carcinoma Characteristics Intestinal\n type Diffuse\n type Incidence Increases\n with age (older adults) Younger\n age group Gender Men>Women Women>Men Histology Well-differentiated\n or moderately differentiated adenocarcinoma with glandular structures and\n intestinal metaplasia Poorly\n differentiated adenocarcinoma with signet ring cells and discohesive cells Spread Hematogenous Transmural/\n lymphatic Molecular\n features · Microsatellite instability, APC gene\n mutations · P53, p16 inactivation · Decreased E-cadherin due to CDH1 mutations\n or epigenetic silencing · P53, P16 inactivation prognosis Better Poor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding diffuse gastric carcinoma except:", "options": [{"label": "A", "text": "Loss of E cadherin expression", "correct": false}, {"label": "B", "text": "Gland formation seen", "correct": true}, {"label": "C", "text": "Signet ring cell seen", "correct": false}, {"label": "D", "text": "Common in young patients", "correct": false}], "correct_answer": "B. Gland formation seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Gland formation seen Diffuse gastric cancer is generally composed of discohesive cells, likely as a result of E-cadherin loss. These cells do not form glands but instead have large mucin vacuoles that expand the cytoplasm and push the nucleus to the periphery, creating a signet-ring cell morphology.</p>\n<p><strong>Highyeild:</strong></p><p>Diffuse Gastric Carcinoma Infiltrating gastric adenocarcinoma with diffuse infiltration of the gastric wall and little to no gland formation Age: Older adults, Males predominance Cause: CDH1 gene mutation Risk factors: Family history of gastric cancer, Helicobacter pylori infection, chronic gastritis, pernicious anaemia, smoking, high salt intake Symptoms: Early stages - Usually symptomatic, later stages- weight loss, dysphagia, nausea, vomiting, abdominal pain Histological features: Poorly cohesive cells , signet ring cells , mucin pools, desmoplastic reaction , often with absence of gland formation</p>\n<p><strong>Table:</strong></p><p>· Lauren ’s classification of Gastric carcinoma Characteristics Intestinal type Diffuse type Incidence Increases with age (older adults) Younger age group Gender Men>Women Women>Men Histology Well-differentiated or moderately differentiated adenocarcinoma with glandular structures and intestinal metaplasia Poorly differentiated adenocarcinoma with signet ring cells and discohesive cells Spread Hematogenous Transmural/ lymphatic Molecular features · Microsatellite instability, APC gene mutations · P53, p16 inactivation · Decreased E-cadherin due to CDH1 mutations or epigenetic silencing · P53, P16 inactivation prognosis Better Poor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the classical histological picture identify the type of tumour:", "options": [{"label": "A", "text": "Signet ring cell carcinoma", "correct": true}, {"label": "B", "text": "Squamous cell carcinoma", "correct": false}, {"label": "C", "text": "Adenocarcinoma", "correct": false}, {"label": "D", "text": "Neuroendocrine tumour", "correct": false}], "correct_answer": "A. Signet ring cell carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157245692-QTDP112015IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Signet ring cell carcinoma The histopathological image showing cells with large mucin vacuole s that are expanding the cytoplasm and pushing the nucleus to the periphery suggests the diagnosis of signet ring cell carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Squamous cell carcinoma: It does not typically produce mucin vacuoles. Instead, it is characterized by the presence of keratin pearls and intercellular bridges. Option: C. Adenocarcinoma: It can produce mucin vacuoles, but signet ring cell carcinoma is a specific type of adenocarcinoma in which the mucin vacuoles are so large that they displace the nucleus to the periphery of the cell. Option: D. Neuroendocrine tumour: These are a distinct group of tumours that arise from neuroendocrine cells, which produce and secrete hormones. They are not characterized by the presence of mucin vacuoles in the cytoplasm.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding gastric lymphoma except:", "options": [{"label": "A", "text": "MALToma is the most common type of lymphoma", "correct": false}, {"label": "B", "text": "It is T-cell lymphoma", "correct": true}, {"label": "C", "text": "There is an increase in the activity of NF-kB", "correct": false}, {"label": "D", "text": "Stomach is most commonly involved", "correct": false}], "correct_answer": "B. It is T-cell lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is T-cell lymphoma Gastric lymphoma is a type of lymphoma that originates in the stomach. These are usually extranodal marginal zone B-cell lymphoma and not T-cell lymphoma.</p>\n<p><strong>Highyeild:</strong></p><p>MALT lymphoma Extranodal marginal zone lymphoma of mucosa-associated lymphoid tissue ( MALT ) Morphologically comprised of heterogeneous B cells Site: Stomach most frequently involves Males: Females = 1:1.2 Age: Usually over 50 years of age Etiology: Infection ( pylori , C.jejune, B.burgdorferi), Autoimmune diseases (Sjogren syndrome, Hashimoto thyroiditis) Pathogenesis: Symptoms: Chronic fatigue, low-grade fever, dyspepsia, nausea and vomiting, altered bowel habits</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A, C, D: All are true</p>\n<p><strong>Extraedge:</strong></p><p>Histology: Gastric MALToma takes the form of a dense lymphocytic infiltrate in the lamina propria. Characteristically, the neoplastic lymphocytes infiltrate the gastric glands focally to create diagnostic lymphoepithelial lesions.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Carney Stratakis syndrome is associated with a mutation in which gene:", "options": [{"label": "A", "text": "KIT", "correct": false}, {"label": "B", "text": "PDGFRA", "correct": false}, {"label": "C", "text": "SDH", "correct": true}, {"label": "D", "text": "BRAF", "correct": false}], "correct_answer": "C. SDH", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>SDH Carney-Stratakis syndrome is an autosomal dominant genetic condition that predisposes individuals to develop gastrointestinal stromal tumours (GISTs) and paragangliomas . It is caused by germline mutations in the succinate dehydrogenase (SDH) genes , which are involved in the mitochondrial electron transport chain.</p>\n<p><strong>Highyeild:</strong></p><p>Carney’s triad Carney-stratakis syndrome Carney’s complex Inheritance Sporadic Autosomal Dominant Autosomal dominant Features GIST, paraganglioma, pulmonary chondroma GIST and paraganglioma SUBSETS: NAME and LAMB syndrome ● Myxomas ● Spotty skin pigmentation ● Endocrine overactivity ● Reproductive organ tumours Molecular changes Unknown SDH mutation PRKAR1A and CNC2 gene mutation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A and B: KIT and PDGFRA are commonly mutated in sporadic GISTs but not in Carney-Stratakis syndrome-associated GISTs. Option: D. BRAF is not associated with GISTs. BRAF gene mutations are found in various types of cancers, including melanoma, papillary thyroid cancer, non-small cell lung cancer, colorectal cancer, ovarian cancer, and hairy cell leukaemia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the origin of Gastrointestinal stromatolites tumour?", "options": [{"label": "A", "text": "Smooth muscles cells", "correct": false}, {"label": "B", "text": "GI pacemaker cells", "correct": true}, {"label": "C", "text": "Enterochromaffin cells", "correct": false}, {"label": "D", "text": "Parietal cells", "correct": false}], "correct_answer": "B. GI pacemaker cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>GI pacemaker cells Gastrointestinal stromal tumours (GISTs) are believed to arise from the interstitial cells of Cajal (ICC) or their precursors. The ICC are specialized cells that are essential for the regulation of gastrointestinal motility and electrical rhythmicity.</p>\n<p><strong>Highyeild:</strong></p><p>GIST- Gastrointestinal stromatolites tumour It is the most common mesenchymal tumour of the abdomen Age: Over 60 years Origin: Interstitial cells of Cajal (pacemaker cells) Markers: CD117 (KIT) best diagnostic marker Most specific: DOG-1 Histopathology: These are composed of the spindle or epithelioid cells that exhibit features of smooth muscle or neural differentiation. Symptoms: Small tumours: Asymptomatic Large tumours: Abdominal pain, nausea, vomiting, and gastrointestinal bleeding.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Smooth muscle cells - Smooth muscle cells make up the muscular layer of the gastrointestinal tract. Leiomyoma arises from them, Option: C. Enterochromaffin cells - These are a type of enteroendocrine cell found that secrete serotonin and other hormones and are involved in the regulation of gastrointestinal motility and secretion. Option: D. Parietal cells - These cells are a type of cell found in the stomach that produce hydrochloric acid and intrinsic factors.</p>\n<p><strong>Extraedge:</strong></p><p>Sporadic GIST : gain of function mutation in KIT and PDGFRA mutation Inherited GIST : seen in carney-stratakis syndrome- loss of function mutation of SDH</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The IHC marker diagnostic of GIST is:", "options": [{"label": "A", "text": "CD 57", "correct": false}, {"label": "B", "text": "CD 45", "correct": false}, {"label": "C", "text": "CD 117", "correct": true}, {"label": "D", "text": "CD 207", "correct": false}], "correct_answer": "C. CD 117", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD 117 The most useful diagnostic marker is KIT (CD 117) which is detectable in Cajal cells and 95% of gastric GISTs by immunohistochemical stains.</p>\n<p><strong>Highyeild:</strong></p><p>GIST- Gastrointestinal stromatolites tumour It is the most common mesenchymal tumour of the abdomen Age: Over 60 years Origin: Interstitial cells of Cajal (pacemaker cells) Markers: CD117 (KIT) best diagnostic marker Most specific: DOG-1 Histopathology: These are composed of the spindle or epithelioid cells that exhibit features of smooth muscle or neural differentiation. Symptoms: Small tumours: Asymptomatic Large tumours: Abdominal pain, nausea, vomiting, and gastrointestinal bleeding.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CD 57: It is an antigen found on natural killer cells and some T cells, and it is not specific for GIST. Option: B. CD 45: It is also known as leukocyte common antigen and is expressed on all leukocytes and not specific to GIST. Option: D. CD 207: It is also known as Langerin is a marker for Langerhans cells, which are antigen-presenting cells in the skin and mucosa, and is not specific to GIST.</p>\n<p><strong>Extraedge:</strong></p><p>Sporadic GIST : gain of function mutation in KIT and PDGFRA mutation Inherited GIST : seen in carney-stratakis syndrome- loss of function mutation of SDH</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 28 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A patient presents with a platelet count of 700 x 10^9/L with abnormalities in the size, shape and granularity of platelets. WBC count of 12 x 10^9 L, haemoglobin of 11g/dl and the absence of the Philadelphia chromosome. The most likely diagnosis would be-", "options": [{"label": "A", "text": "Polycythemia vera", "correct": false}, {"label": "B", "text": "Essential thrombocythemia", "correct": true}, {"label": "C", "text": "Chronic myeloid leukaemia", "correct": false}, {"label": "D", "text": "Leukemoid reaction", "correct": false}], "correct_answer": "B. Essential thrombocythemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Essential thrombocythemia In the given scenario, a patient presents with thrombocytosis with abnormalities in size, shape and granularity of platelets , with normal WBC count & haemoglobin and the absence of the Philadelphia chromosome . The most likely diagnosis, in this case, would be Essential Thrombocythemia</p>\n<p><strong>Highyeild:</strong></p><p>Essential Thrombocytosis (ET): Essential thrombocytosis (ET) is associated with diverse mutations that increase JAK-STAT signalling and mimic constitutive growth factor receptor signalling. ET manifests clinically with elevated platelet counts and is separated from PCV and primary myelofibrosis based on the absence of polycythemia and marrow fibrosis, respectively . M:F 1.5: 1 Age: 50-60 years Thrombosis - Microvascular occlusion, gangrene, Myocardial infarction, DVT, etc Bleeding (abnormal platelet granules). The characteristic symptom is Erythromelalgia , a throbbing and burning of hands and feet caused by occlusion of small arterioles by platelet aggregates, which also may be seen in PCV . Bone marrow cellularity is usually only mildly increased , but megakaryocytes are often markedly increased in number and include abnormally large forms . Peripheral smears usually reveal abnormally large platelets , often accompanied by mild leukocytosis . Modest degrees of extramedullary hematopoiesis may occur, producing mild organomegaly . Essential thrombocytosis. Peripheral blood smear shows marked thrombocytosis including giant platelets approximating the size of surrounding red cells. Diagnosis All 4 major or 3 major +1 minor 1. Major 2. Minor →1 PLC (>4-5 lakh/ul) →↑ Bone marrow proliferation with ↑ megakaryocytes →Rule out CML, PCV, PMF →JAK 2, Calreticulin, MPL mutation → Absence of reactionary thrombocytosis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Polycythemia vera. An increase in Hb or HCT is seen with Panmyelosis. Option: C. Chronic myeloid leukaemia. Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia . Option: D. Leukemoid reaction. The leukemoid reaction is a reactive condition that can mimic CML but is usually secondary to an underlying infection or inflammation, presents with leukocytosis and shift to the left .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Mutation in which gene leads to the development of the congenital nephrotic syndrome:", "options": [{"label": "A", "text": "NPHS 1", "correct": true}, {"label": "B", "text": "NPHS 2", "correct": false}, {"label": "C", "text": "TRPC 6", "correct": false}, {"label": "D", "text": "α-actinin 4", "correct": false}], "correct_answer": "A. NPHS 1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NPHS 1 Congenital nephrotic syndrome is associated with a mutation in the NPHS1 gene , maps to chromosome 19q13, and encodes the protein nephrin . Nephrin is a key component of the slit diaphrag m, the structure that controls glomerular permeability. Several mutations of the NPHS gene have been identified that give rise to congenital nephrotic syndrome of the Finnish type, producing a minimal-change disease like glomerulopathy with extensive foot process effacement.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:B. NPHS 2: Encodes podocin and is associated with steroid-resistant nephrotic syndrome and FSGS Option:C. TRPC-6: Associated with adult-onset FSGS Option:D. α-actinin 4: Encodes for podocin actin-binding protein and is responsible for adult-onset FSGS</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Steroid resistance nephrotic syndrome of childhood is associated with:", "options": [{"label": "A", "text": "Nephrin", "correct": false}, {"label": "B", "text": "Podocin", "correct": true}, {"label": "C", "text": "α-actinin", "correct": false}, {"label": "D", "text": "CD 2AP", "correct": false}], "correct_answer": "B. Podocin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Podocin Podocin is a protein that is essential for the function of the glomerular filtration barrier in the kidney. Mutations in the NPHS2 gene , located on chromosome 1, which encodes for podocin, have been associated with steroid-resistant nephrotic syndrome in children.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Nephrin: It is a key component of the slit diaphragm, the structure that controls glomerular permeability. It is coded by a gene on chr.19 and responsible for the congenital nephrotic syndrome of the Finnish type. Option: C. α-actinin: It is an actin-binding protein that is found in many cell types, including podocytes. Mutations in the ACTN4 gene, which encodes α-actinin-4, have been linked to a rare form of familial FSGS that is resistant to steroid treatment. Option: D. CD2AP: CD2-associated protein (CD2AP) is a scaffolding protein that is involved in the maintenance of the glomerular filtration barrier. Mutations in the CD2AP gene have been associated with the development of familial SRNS and a subset of sporadic SRNS cases.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are proposed etiological factors for FSGS except:", "options": [{"label": "A", "text": "HIV", "correct": false}, {"label": "B", "text": "Sickle cell disease", "correct": false}, {"label": "C", "text": "Hepatitis B virus", "correct": true}, {"label": "D", "text": "Reflux nephropathy", "correct": false}], "correct_answer": "C. Hepatitis B virus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hepatitis B virus The Hepatitis B virus can cause glomerulonephritis and membranous nephropathy, but it is not a known cause of FSGS.</p>\n<p><strong>Highyeild:</strong></p><p>Focal segmental glomerulosclerosis Cause: Primary: Idiopathic Secondary: HIV infection, sickle cell disease, heroin use, obesity, interferon treatment, or congenital malformation, reflux nephropathy The primary disease has an inconsistent response to steroids Diagnosis: Light Microscopy: Segmental Sclerosis and Hyalinosis IF: Often negative but may be present for non-specific focal deposits of IgM, C3, C1 Electron Microscopy: Effacement of foot processes similar to minimal change disease</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., D. HIV, Sickle cell disease, and Reflux nephropathy are all associated with Focal Segmental Glomerulosclerosis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Collapsing glomerulopathy is a variant of-", "options": [{"label": "A", "text": "FSGS", "correct": true}, {"label": "B", "text": "MPGN", "correct": false}, {"label": "C", "text": "Minimal change of disease", "correct": false}, {"label": "D", "text": "Membranous nephropathy", "correct": false}], "correct_answer": "A. FSGS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FSGS Collapsing glomerulopathy is a variant of FSGS (focal segmental glomerulosclerosis), which is a type of nephrotic syndrome. In FSGS , only some segments of the glomerulus are affected by sclerosis , whereas in collapsing glomerulopathy, the entire glomerular tuft collapses due to marked proliferation and hypertrophy of podocytes.</p>\n<p><strong>Highyeild:</strong></p><p>Focal segmental glomerulosclerosis Cause: Primary: Idiopathic Secondary: HIV infection, sickle cell disease, heroin use, obesity, interferon treatment, or congenital malformation, reflux nephropathy The primary disease has an inconsistent response to steroids Diagnosis: Light Microscopy: Segmental Sclerosis and Hyalinosis IF: Often negative but may be present for non-specific focal deposits of IgM, C3, C1 Electron Microscopy: Effacement of foot processes similar to minimal change disease</p>\n<p><strong>Extraedge:</strong></p><p>Histological subtypes of FSGS Histological subtype Characteristics Tip lesion FSGS Sclerosis involves the tip or periphery of the glomerular tuft Perihilar FSGS Sclerosis involves the perihilar region of the glomerular tuft Cellular FSGS Increased mesangial cellularity Collapsing FSGS Characterized by collapsing glomerulopathy and hypertrophy of podocytes Not otherwise specified (NOS) FSGS FSGS that does not fit into the other subtypes</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 40-year-old patient presented with chief complaints of hematuria, mild hypertension, proteinuria, and symptoms of azotemia. The renal biopsy performed is shown below, based on the histological features, what is your diagnosis?", "options": [{"label": "A", "text": "MPGN", "correct": false}, {"label": "B", "text": "Membranous nephropathy", "correct": false}, {"label": "C", "text": "FSGS", "correct": true}, {"label": "D", "text": "Minimal change of disease", "correct": false}], "correct_answer": "C. FSGS", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686835826902-QTDP142008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FSGS The given clinical scenario and a histological image showing focal and segmental glomerular sclerosis and hyalinosis suggest the diagnosis of FSGS- Focal segmental glomerulosclerosis. This can lead to proteinuria, hematuria, hypertension , and ultimately, renal failure. It is a common cause of nephrotic syndrome in adults and can have both primary and secondary causes.</p>\n<p><strong>Highyeild:</strong></p><p>Focal segmental glomerulosclerosis Cause: Primary: Idiopathic Secondary: HIV infection, sickle cell disease, heroin use, obesity, interferon treatment, or congenital malformation The primary disease has an inconsistent response to steroids Diagnosis: Light Microscopy: Segmental Sclerosis and Hyalinosis IF: Often negative but may be present for non-specific focal deposits of IgM, C3, C1 Electron Microscopy: Effacement of foot processes similar to minimal change disease</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. MPGN: It is a type of glomerulonephritis that is characterized by the thickening of the glomerular basement membrane, mesangial hypercellularity, and an increase in the number of intramembranous deposits. Option: B. Membranous nephropathy: It is characterized by the presence of subepithelial immune deposits that form in the glomerular basement membrane. Option: D. Minimal change disease: It is a condition that typically affects children and is characterized by the absence of visible abnormalities in the glomeruli on light microscopy.</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence\n findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have mesangial and\n subepithelial deposits Membranoproliferative Glomerulonephritis Type II (Dense Deposit\n Disease) C3 deposition in the dense intramembranous deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q along the glomerular\n basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3, with different\n patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are the outcomes of acute inflammation except?", "options": [{"label": "A", "text": "Neutrophils Involved", "correct": false}, {"label": "B", "text": "Progression to chronic inflammation", "correct": false}, {"label": "C", "text": "Complete resolution", "correct": false}, {"label": "D", "text": "None of the above", "correct": true}], "correct_answer": "D. None of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above Outcomes of acute inflammation: Complete resolution is usually when the injury is limited or short-lived or when there has been little tissue destruction, and the damaged parenchymal cells can regenerate . Healing by connective tissue replacement (scarring or fibrosis) occurs after substantial tissue destruction when the inflammatory injury involves tissues incapable of regeneration or when there is abundant fibrin exudation in tissue or in serous cavities that cannot be adequately cleared . Progression of the response to chronic inflammation occurs when the acute inflammatory response cannot be resolved due to either the persistence of the injurious agent or some interference with the normal healing process.</p>\n<p><strong>Highyeild:</strong></p><p>Role of inflammatory mediators: Role of Mediators in Different Reactions of Inflammation Reaction of Inflammation Principal Mediators Vasodilation Increased vascular permeability Histamine and serotonin C3 a and C5 a (by liberating vasoactive amines from mast cells, other cells) Leukotrienes C 4 , D 4 , E 4 Chemotaxis, leukocyte recruitment and activation TNF, IL-I Chemokines C3 a , C5 a Leukotriene B 4 Fever IL-1, TNF Prostaglandins Pain Prostaglandins Bradykinin Substance P Tissue damage Lysosomal enzymes of leukocytes Reactive oxygen species IL-I, Interleukin-1; TNF, tumor necrosis factor.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Neutrophils Involved. The outcome of acute inflammation . Option: B. Progression to chronic inflammation. The outcome of acute inflammation . Option: C. Complete resolution. The outcome of acute inflammation .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Principal Actions of Arachidonic Acid Metabolites in Inflammation Action Eicosanoid Vasodilation Prostaglandins PGI 2 (prostacyclin), PGE 1 , PGE 2 , PGD 2 Vasoconstriction Thromboxane A2, leukotrienes C 4 , D 4 , E 4 Increased vascular permeability Leukotrienes C 4 , D 4 , E 4 Chemotaxis, leukocyte adhesion Leukotrienes B 4 , HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following mediator is anti-inflammatory?", "options": [{"label": "A", "text": "Lipoxins", "correct": false}, {"label": "B", "text": "IL-10", "correct": false}, {"label": "C", "text": "TGF- β", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Anti-inflammatory mediators are: Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Anti-inflammatory mediator . Option: B. IL-10. Anti-inflammatory mediator . Option: C. TGF- β. Anti-inflammatory mediator .</p>\n<p><strong>Extraedge:</strong></p><p>Classical and alternative macrophage activation. Different stimuli activate monocytes/macrophages to develop into functionally distinct populations. Classically activated macrophages are induced by microbial products and cytokines, particularly interferon-y (IFN-y). They phagocytose and destroy microbes and dead tissues and can potentiate inflammatory reactions. Alternatively activated macrophages are induced by other cytokines and are important in tissue repair and resolution of inflammation. IL, Interleukin; NO, nitric oxide; ROS, reactive oxygen species; TGF-B, transforming growth factor-B; TLR, Toll-like receptor.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following form of cell death is induced by lipid peroxidation?", "options": [{"label": "A", "text": "Pyroptosis", "correct": false}, {"label": "B", "text": "Necroptosis", "correct": false}, {"label": "C", "text": "Ferroptosis", "correct": true}, {"label": "D", "text": "Programmed necrosis", "correct": false}], "correct_answer": "C. Ferroptosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ferroptosis Ferroptosis is an iron-dependent pathway of cell death induced by lipid peroxidation . It is triggered when excessive intracellular levels of iron or reactive oxygen species (ROS) overwhelm the glutathione-dependent antioxidant defences causing an increase in membrane lipid peroxidation . This leads to a loss of plasma membrane permeability , which ultimately leads to cell death . Unlike necrosis, the process is regulated by specific signals and can, therefore, be prevented by reducing iron levels .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. A pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 . It does not involve lipid peroxidation. Option: B. Necroptosis is programmed cell death without caspase activation . It does not involve lipid peroxidation. Option: D. Programmed necrosis. Necroptosis, also called programmed necrosis , is programmed cell death without caspase activation . It does not involve lipid peroxidation.</p>\n<p><strong>Extraedge:</strong></p><p>Ultrastructurally, the most prominent features are the loss of mitochondrial cristae and ruptured outer mitochondrial membrane . Ferroptosis has been linked to cell death in a variety of human pathologies including cancer, neurodegenerative diseases, and stroke . Iron supplements are thus not given in patients with inflammation RECALL from Pediatrics that when treating patients with Severe Acute Malnutrition , even when the patient has anaemia , Iron is not given initially due to the danger of promoting the free radical generation and bacterial proliferation . Thus Iron is only added after a week of therapy after treatment with antibiotics and when the child has a good appetite and starts gaining weight.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The enzyme that protects the brain from free radical injury is", "options": [{"label": "A", "text": "Myeloperoxidase (MPO)", "correct": false}, {"label": "B", "text": "Superoxide dismutase", "correct": true}, {"label": "C", "text": "MAO", "correct": false}, {"label": "D", "text": "Hydroxylase", "correct": false}], "correct_answer": "B. Superoxide dismutase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Superoxide dismutase Free radical scavengers reduce the levels of free radicals and protect the tissue. Free radicals damage cells via membrane lipid peroxidation, protein modification, and DNA breakage Mechanisms of membrane damage in cell injury. Decreased O2 and increased cytosolic Ca2+ are typically seen in ischemia, but may accompany other forms of cell injury. Reactive oxygen species, which are often produced on reperfusion of ischemic tissues, also cause membrane damage (not shown). Mechanisms of membrane damage in cell injury. Decreased O2 and increased cytosolic Ca2+ are typically seen in ischemia, but may accompany other forms of cell injury. Reactive oxygen species, which are often produced on reperfusion of ischemic tissues, also cause membrane damage (not shown). Mechanisms of membrane damage in cell injury. Decreased O2 and increased cytosolic Ca2+ are typically seen in ischemia, but may accompany other forms of cell injury. Reactive oxygen species, which are often produced on reperfusion of ischemic tissues, also cause membrane damage (not shown). Mechanisms of membrane damage in cell injury. Decreased O2 and increased cytosolic Ca2+ are typically seen in ischemia, but may accompany other forms of cell injury. Reactive oxygen species, which are often produced on reperfusion of ischemic tissues, also cause membrane damage (not shown). Mechanisms of membrane damage in cell injury. Decreased O2 and increased cytosolic Ca2+ are typically seen in ischemia, but may accompany other forms of cell injury. Reactive oxygen species, which are often produced on reperfusion of ischemic tissues, also cause membrane damage (not shown). Free radicals are:- 1) Superoxide: O2- 1) Hydroxyl: OH- (most potent free radical) 2) Peroxy-nitrate: ONOO- 3) Hypochlorite: OCl- (most efficient bacteriocidal agent) Hydrogen peroxide is not a free radical, it is a reactive oxygen species (ROS). Free radical scavengers are:- 1) Anti-oxidants: Vitamin A, C, E 2) Iron binding protein: Transferrin, Ferritin, ceruloplasmin 3) Superoxide dismutase (SOD) 4) Catalase 5) Glutathione peroxidase</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Myeloperoxidase (MPO). MPO-ANCAs are associated with microscopic polyangiitis and Churg-Strauss syndrome. Option: B. Monoamine oxidase (MAO) is involved in removing the neurotransmitters norepinephrine, serotonin and dopamine from the brain . Option: D. Hydroxylases are enzymes that catalyze the addition of -OH (hydroxyl) groups to their substrate during oxidation reactions.</p>\n<p><strong>Extraedge:</strong></p><p>One of the earliest discovered hereditary forms of Amyotrophic lateral sclerosis (ALS)/ Lou Gehrig's disease has mutations in the gene encoding copper-zinc superoxide dismutase (SOD1) on chromosome 21; this variant accounts for about 20% of familial cases. Lou Gehrig disease : Treatment: “ri Lou zole”.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following pigments are involved in free radical injury?", "options": [{"label": "A", "text": "Lipofuscin", "correct": true}, {"label": "B", "text": "Melanin", "correct": false}, {"label": "C", "text": "Bilirubin", "correct": false}, {"label": "D", "text": "Hematin", "correct": false}], "correct_answer": "A. Lipofuscin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lipofuscin Lipofuscin is a telltale sign of free radical injury . Lipofuscin is derived from the lipid peroxidation of polyunsaturated lipids of subcellular membranes. It is golden brown in colour and is deposited peri-nuclearly . It is responsible for the brown atrophy of the liver and heart . It is seen in ageing , Protein Energy Malnutrition , and cancer cachexia . It is also called Wear-and-tear pigment and Lipochrome . Lipofuscin is not injurious to the cell or its functions.</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Melanin is an endogenous, brown-black, pigment formed when the enzyme tyrosinase catalyzes the oxidation of tyrosine to dihydroxyphenylalanine in melanocytes . Option: C. Bilirubin is a yellowish pigment found in bile , which is produced by the liver and stored in the gallbladder. Option: D. Hematin. Haematin is a dark bluish or brownish pigment containing iron in the ferric state, obtained by the oxidation of haem. Haematin inhibits the synthesis of porphyrin and stimulates the synthesis of globin.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding free radicals?", "options": [{"label": "A", "text": "It has a single pair of electrons in the outer shell", "correct": false}, {"label": "B", "text": "It has a single pair of protons in the outer shell", "correct": false}, {"label": "C", "text": "It has a single electron in the outer shell", "correct": true}, {"label": "D", "text": "It has a single proton in the outer shell", "correct": false}], "correct_answer": "C. It has a single electron in the outer shell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It has a single electron in the outer shell Free radicals are chemical species that have a single unpaired electron in an outer orbit . Unpaired electrons are highly reactive and “ attack” and modify adjacent molecules, such as inorganic or organic chemicals- proteins, lipids, carbohydrates, and nucleic acids—many of which are key components of cell membranes and nuclei.</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It has a single pair of electrons in the outer shell. Incorrect . Option: B. It has a single pair of protons in the outer shell. Incorrect . Option: D. It has a single proton in the outer shell. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are the effects of free radical injury?", "options": [{"label": "A", "text": "Mutations", "correct": false}, {"label": "B", "text": "Plasma membrane damage", "correct": false}, {"label": "C", "text": "Misfolding of proteins", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Effects of free radicals on cells are: Damaged DNA causing mutations Damage of proteins causing misfolding of proteins Plasma membrane damage caused by phospholipid damage Lipid peroxidation Cellular ageing</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Mutations. Correct . Option: B. Plasma membrane damage. Correct . Option: C. Misfolding of proteins. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a free radical?", "options": [{"label": "A", "text": "Hydroxyl ion", "correct": false}, {"label": "B", "text": "NO3¯", "correct": false}, {"label": "C", "text": "H2O2", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above The main free radicals are- H2O2 Hydroxyl ion Superoxide ion Peroxynitrite anion (NO3¯ )</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option A: Hydroxyl ion. Correct . Option B: NO3¯. Correct . Option C: H2O2. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are the ways to produce free radicals?", "options": [{"label": "A", "text": "Fenton reaction", "correct": false}, {"label": "B", "text": "Heber Weis reaction", "correct": false}, {"label": "C", "text": "Both A and B", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Both A and B", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Both A and B Free radicals are produced by- Absorption of radiant energy (e.g., ultraviolet light, x-rays ) Reduction-oxidation reactions that occur during normal metabolic processes. Rapid bursts of ROS are produced in activated leukocytes during inflammation . Enzymatic metabolism of exogenous chemicals or drugs. Fenton reaction (H2O2 +Fe2+ ⇆ Fe3+ + ˙OH + OH−) Heber Wies reaction (H2O2+ O2 → H2O2+ O-) Nitric oxide (NO) can act as a free radical and may also be converted to highly reactive peroxynitrite anion (ONOO−) as well as NO2 and NO3− . NOTE: Fenton reaction is a bidirectional reaction .</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fenton reaction. Correct . Option: B. Heber Weis reaction. Correct . Option: C. None. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are helpful in the removal of free radicals except:", "options": [{"label": "A", "text": "Ceruloplasmin", "correct": false}, {"label": "B", "text": "Glutathione peroxidase", "correct": false}, {"label": "C", "text": "Superoxide dismutase", "correct": false}, {"label": "D", "text": "Vitamin B complex", "correct": true}], "correct_answer": "D. Vitamin B complex", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Vitamin B complex Free radicals can be removed by- Antioxidants like Vitamin A, E and C Iron-binding proteins like ferritin, ceruloplasmin, transferrin and lactoferrin Catalase in peroxisomes removes H2O2 Superoxide Dismutase Glutathione Peroxidase</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Ceruloplasmin. Correct . Option: B. Glutathione peroxidase. Correct . Option: C. Superoxide dismutase. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a complete free radical scavenger?", "options": [{"label": "A", "text": "Superoxide dismutase", "correct": true}, {"label": "B", "text": "Glutathione peroxidase", "correct": false}, {"label": "C", "text": "Catalase", "correct": false}, {"label": "D", "text": "Lactoferrin", "correct": false}], "correct_answer": "A. Superoxide dismutase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Superoxide dismutase Superoxide dismutase is used to remove superoxide anion but in turn, it produces H2O2 which is itself a free radical , so it is called an incomplete scavenger . Free radicals can be removed by- Antioxidants like Vitamin A, E and C Iron-binding proteins like ferritin, ceruloplasmin, transferrin and lactoferrin Catalase in peroxisomes removes H2O2 Superoxide Dismutase Glutathione Peroxidase</p>\n<p><strong>Highyeild:</strong></p><p>Effect of free radicals: DNA damage Protein misfolding Phospholipid damage Lipid peroxidation: causes Lipofuscin production (telltale sign of free radical injury) Lipofuscin granules in cardiac myocytes shown by (A) light microscopy (deposits indicated by arrow), and (B) electron microscopy (note the perinuclear, intralysosomal location). Free radicals lead to cellular ageing, cell death by necrosis and even apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Glutathione peroxidase. Complete free radical scavenger . Option: C. Catalase. Complete free radical scavenger . Option: D. Lactoferrin. Complete free radical scavenger .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old man is rushed to the hospital with acute liver failure. He undergoes successful orthotopic liver transplantation; however, the transplanted liver does not produce much bile for the first 3 days. Poor graft function in this patient is thought to be the result of \"reperfusion injury.\" Which of the following substances was the most likely cause of reperfusion injury in this patient's transplanted liver?", "options": [{"label": "A", "text": "Cationic proteins", "correct": false}, {"label": "B", "text": "Free ferric iron", "correct": false}, {"label": "C", "text": "Hydro chlorous acid", "correct": false}, {"label": "D", "text": "Reactive oxygen species", "correct": true}], "correct_answer": "D. Reactive oxygen species", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reactive oxygen species Ischemia/reperfusion (I/R) injury is a common clinical problem that arises in the setting of occlusive cardiovascular disease, infection, transplantation, shock, Restoration of blood flow to ischemic tissues can promote recovery of cells if they are reversibly injured but can also paradoxically exacerbate cell injury and cause cell death . Initially, ischemia produces a type of cellular damage that leads to the generation of free radical species . Subsequently, reperfusion provides abundant molecular oxygen (02) to combine with free radicals to form reactive oxygen species .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators . Necroptosis also acts as a backup mechanism in host defence against certain viruses that encode caspase inhibitors (e.g., cytomegalovirus ). MNEMONIC: The examples of Necroptosis can be remembered with the mnemonic- ‘Necroptosis C an be Sh A R P’: Necroptosis seen in CMV, Steatohepatitis, Acute pancreatitis, Reperfusion injury, Parkinson’s</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cationic proteins. Incorrect . Option: B. Free ferric iron. Incorrect . Option: C. Hydro chlorous acid. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Mechanisms for Reperfusion injury include Oxidative stress Intracellular calcium overload Inflammation Activation of the complement system</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 19 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Based on the histological picture of the gallbladder respected for gallstone shows acute cholecystitis along with:", "options": [{"label": "A", "text": "Hyperplasia", "correct": false}, {"label": "B", "text": "Metaplasia", "correct": true}, {"label": "C", "text": "Hypoplasia", "correct": false}, {"label": "D", "text": "Hypertrophy", "correct": false}], "correct_answer": "B. Metaplasia", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689158743446-QTDP126001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Metaplasia The presence of mucous glands below the subepithelium indicates pyloric metaplasia. Metaplasia refers to the reversible transformation of one type of differentiated cell into another type of differentiated cell.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathology of Acute Cholecystitis Gross : The gallbladder is enlarged The Gallbladder wall is thickened The serosa is covered by fibrin with subserosal hemorrhage The lumen is filled with turbid bile, fibrin, or pus The mucosa is hyperemic, ulcerated, or frankly necrotic Gallstones are present in 80%of cases Histology : Edema and neutrophilic inflammation Vascular congestion Abscess formation and gangrenous necrosis Later neutrophils are replaced by eosinophils (subacute) Ca2+ deposition: “porcelain gallbladder”</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Hyperplasia: It refers to an increase in the number of cells in a tissue or organ, resulting in the enlargement of that tissue or organ. Option:C. Hypoplasia: This refers to an underdevelopment or incomplete development of a tissue or organ, which is not likely to occur in the gallbladder. Option:D. Hypertrophy: This refers to an increase in the size of cells in a tissue or organ, rather than an increase in the number of cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are risk factors for the development of cholesterol stones in the gallbladder except:", "options": [{"label": "A", "text": "Oral contraceptive", "correct": false}, {"label": "B", "text": "Gall bladder stasis", "correct": false}, {"label": "C", "text": "Hyperlipidemia", "correct": false}, {"label": "D", "text": "Chronic hemolytic syndrome", "correct": true}], "correct_answer": "D. Chronic hemolytic syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic hemolytic syndrome The chronic hemolytic syndrome is a condition in which red blood cells are destroyed at an abnormally fast rate, leading to an increased production of bilirubin, which can contribute to the formation of pigment stones in the gallbladder</p>\n<p><strong>Highyeild:</strong></p><p>Pathogens of gallstones</p>\n<p><strong>Extraedge:</strong></p><p>90% of gallstones are 10 % of gallstones are</p>\n<p><strong>Table:</strong></p><p>Risk factors for Gallstones: Cholesterol stones Pigment stones Mixed stones Advancing age Female gender Female sex hormones Oral contraceptive pills Pregnancy Obesity Rapid weight loss Gallbladder stasis Inborn disorder of bile acid metabolism Hyperlipidemia syndromes Chronic hemolytic syndromes Biliary infection Gastrointestinal disorders: Cronh’s disease,\n ileal resection or bypass, cystic fibrosis with pancreatic\n insufficiency Hereditary blood disorders Combination of risk factors for cholesterol\n and pigment stones</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The glomerular basement membrane is predominantly composed of which type of collagen:", "options": [{"label": "A", "text": "V", "correct": false}, {"label": "B", "text": "VI", "correct": false}, {"label": "C", "text": "IV", "correct": true}, {"label": "D", "text": "IX", "correct": false}], "correct_answer": "C. IV", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IV The GBM consists of collagen- mostly type IV , laminin, polyanionic proteoglycans (mostly heparan sulfate), fibronectin, entactin, and several other glycoproteins.</p>\n<p><strong>Table:</strong></p><p>Collagen type and tissue distribution Collagen type Tissue distribution I Bone, tendons, Dermis II Cartilage, Vitreous body,\n Nucleus pulposus III Skin, blood vessels,\n uterus, IV Basement membrane, lens VII Anchoring fibrils VIII Endothelium XIV Skin, cornea XVII Hemidesmosomes</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Podocytes are seen in:", "options": [{"label": "A", "text": "PCT", "correct": false}, {"label": "B", "text": "DCT", "correct": false}, {"label": "C", "text": "Collecting tubules of the kidney", "correct": false}, {"label": "D", "text": "Bowman’s space", "correct": true}], "correct_answer": "D. Bowman’s space", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bowman’s space Podocytes are specialized cells that are found in Bowman's capsule of the kidney and are important for the filtration function of the glomerulus.</p>\n<p><strong>Highyeild:</strong></p><p>Glomerular anatomy The glomerulus is a small network of blood vessels located within the renal corpuscle of the kidney. It consists of a tuft of capillaries that are surrounded by Bowman's capsule , which is a double-walled cup-like structure. The afferent arteriole brings blood into the glomerulus, while the efferent arteriole carries blood away from it. The glomerular capillaries are fenestrated , meaning they have small pores or holes that allow for the filtration of blood plasma. The glomerular basement membrane (GBM) is a thin layer of extracellular matrix that lies between the capillaries and Bowman's capsule. It acts as a filtration barrier that prevents the passage of large molecules, such as proteins, into the urine. The visceral layer of Bowman's capsule is composed of specialized cells called podocytes , which wrap around the capillaries and form foot-like projections known as pedicels. The pedicels interdigitate with each other, leaving narrow filtration slits between them that are also part of the filtration barrier. The mesangium is a matrix of cells and extracellular material that supports the glomerular capillaries and plays a role in regulating blood flow through the capillaries.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. PCT: (proximal convoluted tubule) is a tubular structure of the nephron that is responsible for the reabsorption of ions, water, and nutrients from the glomerular filtrate. Option: B. DCT:(distal convoluted tubule) is another tubular structure of the nephron that is responsible for the reabsorption and secretion of ions and water. Option: C. Collecting tubules: CT of the kidney are responsible for the reabsorption of water and electrolytes from the urine and the excretion of waste products.</p>\n<p><strong>Extraedge:</strong></p><p>Slit diaphragm It is a specialized structure in the podocyte foot processes of the glomerulus that plays a critical role in the filtration barrier of the kidney. The integrity of the slit diaphragm is maintained by several proteins, including: Nephrin : It is a transmembrane protein that forms a homodimer and is a key component of the slit diaphragm. Podocin : It is a membrane protein that interacts with nephrin and stabilizes the slit diaphragm. CD2-associated protein (CD2AP) : It is a cytoplasmic protein that binds to nephrin and podocin and is involved in the regulation of the actin cytoskeleton. Actin : It is a cytoskeletal protein that provides structural support to the foot processes and is essential for maintaining the integrity of the slit diaphragm. α-Actinin-4: It is a cytoskeletal protein that crosslinks actin filaments and stabilizes the slit diaphragm.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The best special stain to detect the increased thickness of the glomerular basement membrane is-", "options": [{"label": "A", "text": "VVG", "correct": false}, {"label": "B", "text": "PAS", "correct": true}, {"label": "C", "text": "Von Kossa", "correct": false}, {"label": "D", "text": "Methyl violet", "correct": false}], "correct_answer": "B. PAS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PAS PAS (Periodic Acid-Schiff) stain is the best special stain to detect an increase in the thickness of the glomerular basement membrane.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. VVG: It is a stain that uses a combination of hematoxylin, resorcin-fuchsin, and picric acid. It stains elastic fibres black, and collagen fibres yellow to red. Option: C. Von Kossa: This stain is used to identify calcium deposits. Option: D. Methyl violet: It is used for staining amyloid deposits, both of which are not relevant for detecting the thickening of the glomerular basement membrane.</p>\n<p><strong>Table:</strong></p><p>Commonly used pathological stains Stain Use Hematoxylin and Eosin (H&E) General staining of tissues, used to visualize\n cellular and tissue morphology Periodic Acid-Schiff (PAS) Carbohydrate-rich structures like glycogen,\n basement membranes, and fungal organisms Masson's trichrome Connective tissue, muscle, and collagen fibres Congo red Amyloidosis Ziehl-Neelsen Acid-fast organisms like Mycobacterium\n tuberculosis Wright-Giemsa Blood cells and bone marrow Prussian blue Iron deposition in tissues, as seen in\n hemochromatosis Alcian blue Acidic mucopolysaccharides, such as those found\n in intestinal goblet cells Toluidine blue Mast cells and their granules</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "T cells recognize which antigen in graft rejection –", "options": [{"label": "A", "text": "MHC II", "correct": false}, {"label": "B", "text": "MHC I", "correct": false}, {"label": "C", "text": "Both MHC I and II", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Both MHC I and II", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Both MHC I and II</p>\n<p><strong>Highyeild:</strong></p><p>Rejection is a process in which T lymphocytes and antibodies produced against graft antigens react against and destroy tissue grafts . Rejection is most commonly seen within the initial months after transplantation and is heralded by clinical and biochemical signs of organ failure . Following transplantation, the recipient’s T cells recognize donor HLA antigens from the graft (the allogeneic antigens, or alloantigens) by two pathways : Direct pathway: The graft antigens are either presented directly to recipient T cells by graft APCs Indirect pathway: The graft antigens are picked up by host APCs , processed (like any other foreign antigen), and presented to host T cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. MHC II. Correct . Option: B. MHC I. Correct . Option: D. None. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>It was thought that the direct killing of graft cells by CD 8+ CTLs is a major component of the reaction. However, more recent studies have established that an important component of this process is an inflammatory reaction in the graft triggered by cytokines secreted by activated CD4+ T cells . The inflammation results in increased vascular permeability and local accumulation of mononuclear cells (lymphocytes and macrophages), and graft injury is caused by the activated macrophage. Hence both MHC I and II are recognized in graft rejection .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hyperacute rejection occurs within:", "options": [{"label": "A", "text": "12 hours", "correct": true}, {"label": "B", "text": "2 weeks", "correct": false}, {"label": "C", "text": "1 month", "correct": false}, {"label": "D", "text": "3 months", "correct": false}], "correct_answer": "A. 12 hours", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>12 hours Hyperacute rejection This form of rejection occurs within minutes or hours after transplantation . A hyperacutely rejecting kidney rapidly becomes cyanotic, mottled, and flaccid, and may excrete a mere few drops of bloody urine . Immunoglobulin and complement are deposited in the vessel wall , causing endothelial injury and fibrin-platelet thrombi . Neutrophils rapidly accumulate within arterioles, glomeruli, and peritubular capillaries. As these changes become diffuse and intense, the glomeruli undergo thrombotic occlusion of the capillaries , and fibrinoid necrosis occurs in arterial walls</p>\n<p><strong>Highyeild:</strong></p><p>Types of graft/transplant: Type of graft/transplant Definition Orthotopic Transplant Organ implanted in the same anatomical location in the recipient as it was in the donor with the removal of the diseased organ. Eg: Heart, Lung, Intestine, Liver. A heterotopic Transplant Organ is implanted in a different anatomical location in the recipient without the removal of the diseased organ. Eg: Kidney, Pancreas. Auxillary Transplant Partial tissue donor acts as temporary support for the recipient's diseased/injured organ without removal of the diseased/injured organ. Eg: Left lobe of the liver. Autotransplant Transfer of cells/tissues/organs within the same person. “Self transplant” Allotransplant Transfer of cells/tissues/organs within the same species. “Between two individuals of the same species” Xenotransplant Transfer of cells/tissues/organs in a different species. “Between different species” Isotransplant Transfer of cells/tissues/organs within genetically identical individuals. “Been identical twins”</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. 2 weeks. Incorrect . Option: C. 1 month. Incorrect . Option: D. 3 months. Incorrect .</p>\n<p><strong>Table:</strong></p><p>Mechanism\nof graft rejection on the basis of timing:</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements about graft versus host disease is least correct:", "options": [{"label": "A", "text": "Occurs when the host is immunocompromised", "correct": false}, {"label": "B", "text": "Occurs when donor cells are immunocompromised", "correct": true}, {"label": "C", "text": "Is also called Runt disease", "correct": false}, {"label": "D", "text": "A common cause is stem cell transplantation", "correct": false}], "correct_answer": "B. Occurs when donor cells are immunocompromised", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Occurs when donor cells are immunocompromised Donor cells should be Immunocompetent .</p>\n<p><strong>Highyeild:</strong></p><p>Graft vs Host Disease , GVHD also known as Runts disease , occurs when immunologically competent cells or their precursors are transplanted into immunologically crippled recipients , and the transferred cells recognize alloantigens in the host and attack host tissues . It is seen most commonly in the setting of Hematopoietic Stem Cell (HSC) Transplantation but, rarely, may occur following transplantation of solid organs rich in lymphoid cells (e.g., the liver ) or transfusion of unirradiated blood . When immune-compromised recipients receive HSC preparations from allogeneic donors , the immunocompetent T cells present in the donor inoculum recognize the recipient's HLA antigens as foreign and react against them. Acute GVHD: Occurs within days to weeks after allogeneic HSC transplantation. Although any organ may be affected, the major clinical manifestations result from the involvement of the immune system and epithelia of the skin, liver, and intestines . Clinical features include Rash , Jaundice , and Bloody diarrhea . Chronic GVHD: May follow the acute syndrome or may occur insidiously. These patients have extensive cutaneous injury, with the destruction of skin appendages and fibrosis of the dermis. The changes may resemble systemic sclerosis , other features include cholestatic jaundice and esophageal strictures , and patients experience recurrent and life-threatening infections . To minimize GVHD , HSC transplants are done between donor and recipient that are HLA matched using precise DNA sequencing-based methods for molecular typing of HLA alleles.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Occurs when the host is immunocompromised. Correct . Option: C. Is also called Runt disease. Correct . Option: D. A common cause is stem cell transplantation. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>When immunocompetent donor T cells attack and destroy immunosuppressed recipient tissue: Normal tissue destroyed causes GVHD Tumor cells destroyed causes Graft vs Tumor effect also called Graft vs Leukemia (Good effect) When donor T cells are irradiated they will reduce risk of GVHD but will increase risk of recurrence of tumor in host .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Acute graft versus host disease reaction occurs in all except-", "options": [{"label": "A", "text": "Liver", "correct": false}, {"label": "B", "text": "Adrenal", "correct": true}, {"label": "C", "text": "GIT", "correct": false}, {"label": "D", "text": "Skin", "correct": false}], "correct_answer": "B. Adrenal", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adrenal Acute GVHD occurs within days to weeks after allogeneic bone marrow transplantation. Although any organ may be affected, the major clinical manifestations result from the involvement of the immune system and epithelia of the skin, liver, and intestines . Involvement of skin in GVHD is manifested by a generalized rash that may lead to desquamation in severe cases. Destruction of small bile ducts gives rise to jaundice and mucosal ulceration of the gut resulting in bloody diarrhea .</p>\n<p><strong>Highyeild:</strong></p><p>Graft vs Host Disease , GVHD also known as Runts disease , occurs when immunologically competent cells or their precursors are transplanted into immunologically crippled recipients , and the transferred cells recognize alloantigens in the host and attack host tissues . It is seen most commonly in the setting of Hematopoietic Stem Cell (HSC) Transplantation but, rarely, may occur following transplantation of solid organs rich in lymphoid cells (e.g., the liver ) or transfusion of unirradiated blood . When immune-compromised recipients receive HSC preparations from allogeneic donors , the immunocompetent T cells present in the donor inoculum recognize the recipient's HLA antigens as foreign and react against them. Acute GVHD: Occurs within days to weeks after allogeneic HSC transplantation. Although any organ may be affected, the major clinical manifestations result from the involvement of the immune system and epithelia of the skin, liver, and intestines . Clinical features include Rash , Jaundice , and Bloody diarrhea . Chronic GVHD: May follow the acute syndrome or may occur insidiously. These patients have extensive cutaneous injury, with the destruction of skin appendages and fibrosis of the dermis. The changes may resemble systemic sclerosis , other features include cholestatic jaundice and esophageal strictures , and patients experience recurrent and life-threatening infections . To minimize GVHD , HSC transplants are done between donor and recipient that are HLA matched using precise DNA sequencing-based methods for molecular typing of HLA alleles.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Liver. Correct . Option: C. GIT. Correct . Option: D. Skin. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>When immunocompetent donor T cells attack and destroy immunosuppressed recipient tissue: Normal tissue destroyed causes GVHD Tumor cells destroyed causes Graft vs Tumor effect also called Graft vs Leukemia (Good effect) When donor T cells are irradiated they will reduce risk of GVHD but will increase risk of recurrence of tumor in host .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "True regarding oncogenes are all except –", "options": [{"label": "A", "text": "Derived from proto-oncogenes", "correct": false}, {"label": "B", "text": "Oncogenes code for specific protein", "correct": false}, {"label": "C", "text": "Point mutation is seen", "correct": false}, {"label": "D", "text": "Multiple growth factors govern the gene", "correct": true}], "correct_answer": "D. Multiple growth factors govern the gene", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple growth factors govern the gene Genes that promote autonomous cell growth in cancer cells are called oncogenes , and their unmutated cellular counterparts are called proto-oncogenes . Oncogenes are created by mutations in proto-oncogenes and encode proteins called oncoproteins that have the ability to promote cell growth in the absence of normal growth-promoting signals . Oncoproteins resemble the normal products of proto-oncogenes but bear mutations that often inactivate internal regulatory elements; consequently, their activity in cells does not depend on external signals . Cells expressing oncoproteins are thus freed from the normal checkpoints and controls that limit growth , and as a result proliferate excessively .</p>\n<p><strong>Highyeild:</strong></p><p>Gain of function mutation in KIT is seen in Gastrointestinal tumors (GIST). Gain of function mutation in KRAS is seen in colon, lung, and pancreatic tumors. Inactivation of TP53 and RB genes is associated with small cell cancer. PDGFR-β amplification is seen with Gliomas and Leukemias. Burkitt’s lymphoma is associated with translocation of cMYC t(8:14) or t(8:22).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Derived from proto-oncogenes. True . Option: B. Oncogenes code for a specific protein. True . Option: C. Point mutation is seen. True .</p>\n<p><strong>Extraedge:</strong></p><p>Neuroblastoma is associated with translocations of nMYC. Retinoblastoma is associated with a mutation in the Rb gene. Pleomorphic adenoma is associated with chromosomal rearrangement causing overexpression of PLAG-1.</p>\n<p><strong>Table:</strong></p><p>Selected Oncogenes, Their Mode\nof Activation, and Associated Human Tumors Category Proto-Oncogene Mode of Activation in Tumor Associated Human Tumor Growth Factors PDGF- β PDGFB Overexpression Astrocytoma Fibroblast growth factors HSTI FGF3 Overexpression Amplification Osteosarcoma Stomach cancer Bladder cancer Breast cancer Melanoma TGF-α TGFA Overexpression Astrocytomas HGF HGF Overexpression Hepatocellular carcinomas Thyroid cancer Growth Factor Receptors EGF-receptor family ERBBI (EGFR) ERBB2 (HER Mutation Amplification Adenocarcinoma of lung Breast\n carcinoma FMS-like tyrosine kinase 3 FLT3 Point mutation or small\n duplications Leukemia Receptor for neurotrophic\n factors RET Point mutation Multiple endocrine neoplasia\n 2A and B, familial medullary thyroid carcinomas PDGF receptor PDGFRB Amplification, translocation Gliomas, leukemias Receptor for KIT ligand KIT Point mutation Gastrointestinal stromal\n tumors, seminomas, leukemias ALK receptor ALK Translocation Point mutation Adenocarcinoma of lung,\n certain lymphomas Neuroblastoma Proteins Involved in Signal\n Transduction GTP-binding (G) proteins KRAS HRAS NRAS GNAQ GNAS Point mutation Point mutation Point mutation Point mutation Point mutation Colon, lung, and pancreatic\n tumors Bladder and kidney tumors Melanomas, hematologic\n malignancies Uveal melanoma Pituitary adenoma, other\n endocrine tumors Nonreceptor tyrosine kinase ABL Translocation Chronic myelogenous leukemia\n Acute lymphoblastic leukemia RAS signal transduction BRAF Point mutation Melanomas, leukemias, colon\n carcinoma, others Notch signal transduction NOTCHI Point mutation, translocation Leukemias, lymphomas, breast\n carcinoma JAK/STAT signal transduction JAK2 Point mutation, translocation Myeloproliferative disorders Acute lymphoblastic leukemia Nuclear Regulatory Proteins Transcriptional activators MYC NMYC Translocation Amplification Burkitt lymphoma Neuroblastoma Cell Cycle Regulators Cyclins CCNDI (cyclin DI) Translocation Amplification Mantle cell lymphoma, multiple\n myeloma Breast and esophageal cancers Cyclin-dependent kinase CDK4 Amplification or point\n mutation Glioblastoma, melanoma,\n sarcoma Tumor Suppressor genes: . 1. On the cell surface TGB- β : colon cancer, Breast cancer 2. Under the cell Surface NF-1 (179) - Neurofibromatosis 1 NF-2 (229) - Neurofibromatosis 2 3. Cytoplasm PTEN - Endometrial cancer (Cowden\n Syndrome) APC-Familial Adenomatous Polyposis SMAD-Pancreatic cancer 4. Nucleus p53 (17p) - Li-Fraumeni Syndrome Rb (139) - Retinoblastoma, osteosarcoma WT 1 (11 p) - Wilm's Tumor BRCA 1 (17p) - Breast cancer, ovarian\n cance BRCA 2 (139) - Breast cancer (male).\n Prostate cancer, Gall Bladder cancer Mc Gene mutated - p53 Mc oncogene - K-RAS BRCA 1, BRAC 2-DNA Repair Genes</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Following are the mechanisms by which p53 exerts its tumor suppressor activity EXCEPT:", "options": [{"label": "A", "text": "Activates telomerase activity", "correct": true}, {"label": "B", "text": "Upregulates cyclin-dependent kinase inhibitors", "correct": false}, {"label": "C", "text": "Promotion of apoptosis of cells with injured DNA", "correct": false}, {"label": "D", "text": "Promotion of DNA repair", "correct": false}], "correct_answer": "A. Activates telomerase activity", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Activates telomerase activity p53 downregulates telomerase activity.</p>\n<p><strong>Highyeild:</strong></p><p>p53 gene Present on Chromosome 17p13 . Also known as Guardian of Genome and Molecular Policeman of Gene . Tumor Suppressor gene that regulates cell cycle progression, DNA repair, cellular senescence, and apoptosis, is the most frequently mutated gene in human cancers. The role of p53 in maintaining the integrity of the genome. Activation of normal p53 by DNA-damaging agents or by hypoxia leads to cell cycle arrest in G, and induction of DNA repair by transcriptional upregulation of the cyclin-dependent kinase inhibitor CDKNIA (encoding the cyclin- dependent kinase inhibitor p21) and GADD45 genes. Successful repair of DNA allows cells to proceed with the cell cycle; if DNA repair fails, p53 triggers either apoptosis or senescence. In cells with loss or mutations of the p53 gene, DNA damage does not induce cell cycle arrest or DNA repair, and genetically damaged cells proliferate, giving rise eventually to malignant neoplasms. Germline mutation of p53: Li Fraumeni syndrome . Sporadic mutations are associated with Tumours in Brain, Breast, Lung, Adrenal, and Skin (SCC) . The p53 protein is the central monitor of stress in the cell and can be activated by anoxia, inappropriate signaling by mutated oncoproteins, or DNA damage . p53 controls the expression and activity of proteins involved in cell cycle arrest, DNA repair, cellular senescence, and apoptosis. DNA damage is sensed by complexes containing kinases of the ATM/ATR family ; these kinases phosphorylate p53, liberating it from inhibitors such as MDM2. Active p53 then upregulates the expression of proteins such as the cyclin-dependent kinase inhibitor p21 , thereby causing cell-cycle arrest at the G1 /S checkpoint . This pause allows cells to repair DNA damage. If DNA damage cannot be repaired, p53 induces additional events that lead to cellular senescence or apoptosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Upregulates cyclin-dependent kinase inhibitors. Correct . Option: C. Promotion of apoptosis of cells with injured DNA. Correct . Option: D. Promotion of DNA repair. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The majority of human cancers demonstrate biallelic loss-of-function mutations in TP53 . Like RB, p53 is inactivated by viral oncoproteins, such as the E6 protein of HPV .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following protein is called “Governor of proliferation”:", "options": [{"label": "A", "text": "RB", "correct": true}, {"label": "B", "text": "TP53", "correct": false}, {"label": "C", "text": "APC", "correct": false}, {"label": "D", "text": "PTEN", "correct": false}], "correct_answer": "A. RB", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RB</p>\n<p><strong>Highyeild:</strong></p><p>RB Present on Chromosome 13q14 . Also known as Governor of the Cell Cycle . Tumor Suppressor gene which when hypophosphorylated, exerts antiproliferative effects by binding and inhibiting E2F transcription factors that regulate genes required for cells to pass through the G1-S phase cell cycle checkpoint . Normal growth factor signaling leads to RB hyperphosphorylation and inactivation , thus promoting cell cycle progression . The antiproliferative effect of RB is evaded in cancers through a variety of mechanisms, including Loss-of-function mutations affecting RB Gene amplifications of CDK4 and cyclin D genes Loss of cyclin-dependent kinase inhibitors (p16/INK4a) Viral oncoproteins that bind and inhibit RB ( E7 protein in HPV ). The role of RB in regulating the G i -S checkpoint of the cell cycle. Hypophosphorylated RB in complex with the E2F transcription factors binds to DNA, recruits chromatin-modifying factors (histone deacetylases and histone methyltransferases), and inhibits transcription of genes whose products are required for the S phase of the cell cycle. When RB is phosphorylated by the cyclin D-CDK4, cyclin D-CDK6, and cyclin E-CDK2 complexes, it releases E2F. The latter then activates transcription of S-phase genes. Phosphorylation of RB is inhibited by cyclin-dependent kinase inhibitors because they inactivate cyclin-CDK complexes. In most cancers, the G-S checkpoint is defective as a result of mutation of one of four genes that regulate the phosphorylation of RB; these genes are RB, CDK4, the genes encoding cyclin D proteins, and CDKN2A (p16). EGF, Epidermal growth factor; PDGF, platelet-derived growth factor; TGF-β, transforming growth factor-β.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. TP53. Also known as Guardian of Genome and Molecular Policeman of Gene . Option: C. APC. Incorrect . Option: D. PTEN. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>MNEMONIC: RB in a Hyper phosphorylated state becomes Hyper and causes Translation ie cell cycle progression .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Genomic sequencing lead to the identification of dozens to hundreds of chromosome break occurring within or across the entirety of a single chromosome in which the chromosome is shattered and then reassembled in a haphazard way is known as:", "options": [{"label": "A", "text": "Subcytogenic", "correct": false}, {"label": "B", "text": "Indels", "correct": false}, {"label": "C", "text": "Chromothrypsis", "correct": true}, {"label": "D", "text": "Mutation", "correct": false}], "correct_answer": "C. Chromothrypsis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chromothrypsis Genomic sequencing has revealed numerous “cryptic” (sub cytogenetic) rearrangements , mainly small deletions and insertions (“indels”), as well as chromothripsis, in which a chromosome is “shattered” and then reassembled in a haphazard way. Genomic sequencing has revealed not only many simple rearrangements (e.g., small deletions, duplications, or inversions) that were not appreciated by prior methods but also much more dramatic chromosome \"catastrophes\" termed chromothripsis (literally, chromosome shattering ). Chromothrypsis is observed in 1% to 2% of cancers as a whole and is particularly common in osteosarcomas and gliomas . It appears to result from a single event in which dozens to hundreds of chromosome breaks occur within part or across the entirety of a single chromosome or several chromosomes . The genesis of these breaks is unknown, but DNA repair mechanisms are activated in affected cells that stitch the pieces together in a haphazard way , creating many chromosome rearrangements and also resulting in the loss of some chromosome segments . It is hypothesized that such catastrophic events may by chance mutate multiple cancer genes simultaneously thereby expediting the process of carcinogenesis .</p>\n<p><strong>Highyeild:</strong></p><p>Cancers associated with some important oncogenes: table,tr,th,td {border:1px solid black;} Oncogenes Associated cancers c-MYC Burkitt’s Lymphoma Adenocarcinoma of breast, lung, and colon N-MYC Neuroblastoma L-MYC Small cell carcinoma of lung H-KRAS Bladder and Kidney tumors N-RAS Melanoma AML K-RAS Colon, Lung, and pancreatic tumors</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Subcytogenic. Incorrect. Option: B. Indels. Incorrect. Option: D. Mutation. Incorrect.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following image depicts a technique used in the pathologic diagnosis of cancers. Identify the technique and the tumor it most likely represents:", "options": [{"label": "A", "text": "Histopathological examination – Leiomyoma uterus", "correct": false}, {"label": "B", "text": "Immunohistochemistry – Breast cancer", "correct": true}, {"label": "C", "text": "Pap smear – Cervical carcinoma", "correct": false}, {"label": "D", "text": "Electron microscopy – Melanoma", "correct": false}], "correct_answer": "B. Immunohistochemistry – Breast cancer", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689150326328-QTDP057006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Immunohistochemistry – Breast cancer The above image clearly demonstrates Immunohistochemistry staining (IHC). This technique is useful to detect lymphomas, breast cancers, melanoma , etc. The given image represents nuclear staining . Now, ER (Estrogen Receptor) and PR (Progesterone Receptor) are present inside the nucleus , so, this case is probably a case of ER or PR-positive breast cancer . Hence, the correct answer is option B.</p>\n<p><strong>Highyeild:</strong></p><p>IHC staining Cytokeratin: Carcinoma Vimentin: Sarcoma Desmin: Rhabdomyosarcoma HMB-45: Melanoma S-100: Langerhans Cell Histiocytosis Synaptophysin: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca Chromogranin: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca Nonspecific Enolase: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca CD 56: Neuroendocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Histopathological examination – Leiomyoma uterus,is incorrect because Histopathological examination makes use of H & E stain which stains pink and blue under microscopy. Hence, this option is incorrect. Option:C. Pap smear – Cervical carcinoma,is incorrect because Pap smear is a cytologic technique that demonstrates numerous cells with pink and purple cytoplasm and this is considered a gold standard for screening of cervical carcinoma . Option:D. Electron microscopy – Melanoma,is incorrect because electron microscopy is a technique that helps in the visualization of the ultrastructure of tissue . It is particularly useful for better visualization of changes in the nucleus.</p>\n<p><strong>Extraedge:</strong></p><p>Uses of IHC: Categorization of undifferentiated malignant tumors: The presence of cytokeratins , detected by immunohistochemistry, points to an epithelial origin ( carcinoma ), whereas desmin is specific for neoplasms of muscle cell origin , and hematologic malignancies lack these cytoskeletal structures. Determination of site of origin of metastatic tumor: In cases in which the origin of the tumor is unknown , immunohistochemical detection of tissue-specific or organ-specific antigens in a biopsy specimen of the metastatic deposit can lead to the identification of the tumor source. Detection of molecules that have prognostic or therapeutic significance: Immunohistochemical detection of hormone (estrogen/progesterone) receptors in breast cancer cell s is of prognostic and therapeutic value because these cancers are susceptible to anti-estrogen therapy .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 30-year-old woman presents with complaints of lumpiness in the breast. She undergoes surgical resection of this mass. The image of the resected mass is shown below. What can you infer about the nature of this mass from the following image?", "options": [{"label": "A", "text": "Metastasis", "correct": false}, {"label": "B", "text": "Malignant tumor", "correct": false}, {"label": "C", "text": "Benign tumor", "correct": true}, {"label": "D", "text": "Hamartoma", "correct": false}], "correct_answer": "C. Benign tumor", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689150333706-QTDP057007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Benign tumor The above image shows a sharply demarcated , well-circumscribed encapsulated mass which is tan-colored. It can be easily differentiated from the surrounding breast tissue which is white in color. This appearance is classical for Fibroadenoma of the breast , which is a benign tumor of the breast seen in young females of the reproductive age group . Hence, the correct answer is Option C.</p>\n<p><strong>Highyeild:</strong></p><p>Choristoma: Normal tissue at abnormal site, eg: Normal Gastric mucosa in the pancreatic biopsy . Hamartoma: Abnormal tissue at normal site, eg: Dysplastic lung tissue in a lump . Comparisons Between Benign and Malignant Tumors. Characteristics Benign Malignant Differentiation/ anaplasia Well differentiated; structure sometimes typical of tissue of origin Some lack of differentiation (anaplasia); structure often atypical Rate of growth Usually progressive and slow; may come to a standstill or regress; mitotic figures rare and normal Erratic, may be slow to rapid; mitotic figures may be numerous and abnormal Local invasion Usually cohesive, expansile, well-demarcated masses that do not invade or infiltrate surrounding normal tissues Locally invasive, infiltrating surrounding tissue; sometimes may be misleadingly cohesive and expansile Metastasis Absent Frequent; more likely with large undifferentiated primary tumors</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Metastasis, is incorrect because metastasis is usually seen as multiple small masses in the breast which cannot be appreciated in this tumor. Option: B. Malignant tumor,is incorrect because malignant tumor is seen with invasion of surrounding tissue . So, normal breast tissue will not be well differentiated and moreover, normal breast tissue and the pathological tumor will be difficult to demarcate. Option: D . Hamartoma,is incorrect because hamartomas are disorganized masses composed of cells indigenous to the involved site . They are not encapsulated , thus, the above image cannot be a hamartoma.</p>\n<p><strong>Extraedge:</strong></p><p>Comparisons Between Benign and Malignant Tumors Characteristics Benign Malignant Differentiation/ anaplasia Well differentiated; structure sometimes typical of tissue of origin Some lack of differentiation (anaplasia); structure often atypical Rate of growth Usually progressive and slow; may come to a standstill or regress; mitotic figures rare and normal Erratic, may be slow to rapid; mitotic figures may be numerous and abnormal Local invasion Usually cohesive, expansile, well-demarcated masses that do not invade or infiltrate surrounding normal tissues Locally invasive, infiltrating surrounding tissue; sometimes may be misleadingly cohesive and expansile Metastasis Absent Frequent; more likely with large undifferentiated primary tumors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 56-year-old male presents with a 6-month history of cough and hemoptysis. He also states that he lost around 6 kgs of body weight during this duration. He has smoked cigarettes every day for 40 years and he also drinks alcohol occasionally. A diagnosis of lung carcinoma is made. Which of the following is the most likely route of spread for this cancer?", "options": [{"label": "A", "text": "Hematogenous spread", "correct": false}, {"label": "B", "text": "Direct seeding of body cavities", "correct": false}, {"label": "C", "text": "Lymphatic spread", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Lymphatic spread", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphatic spread Dissemination of cancers occurs through three pathways: Direct seeding of body cavities or surfaces Ovarian Cancer Lymphatic spread Carcinomas eg Lung, Breast Hematogenous spread Sarcomas Some Carcinomas: Renal Cell Ca, Hepatocellular Ca, Follicular Thyroid Ca This patient is suffering from lung cancer and it is a type of carcinoma because of its origin from epithelium . Carcinomas usually spread via the lymphatic route , that is, with the help of regional lymph nodes , to other organs. Hence, the correct answer for this question is Option C.</p>\n<p><strong>Highyeild:</strong></p><p>Mechanism of activation of protooncogenes: Mutation Promoter insertion Enhancer insertion Chromosomal translocation Gene amplification</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hematogenous spread. Hematogenous spread is seen with sarcomas . Option: B. Direct seeding of body cavities. Direct seeding of body cavities is most commonly seen with ovarian tumors which directly spread to the peritoneal cavity. Option: D. None of the above. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25-year-old female presents with complaints of abdominal pain and vaginal bleeding. She also reports that she has lost interest in sexual intercourse because of pain during coitus as well as post-coital bleeding. She is sexually active with multiple partners and uses condoms inconsistently. A pap smear reveals the presence of atypical cells with clear cytoplasm. A diagnosis of HPV infection is made. The patient inquires as to why this infection is responsible for her condition. The doctor explains that there are two proteins secreted by HPV which cause the inhibition of two tumor suppressor genes. Which tumor suppressor genes are the doctor referring to?", "options": [{"label": "A", "text": "E6, E7", "correct": false}, {"label": "B", "text": "Rb, p53", "correct": true}, {"label": "C", "text": "LMP1, BCL2", "correct": false}, {"label": "D", "text": "BRCA1, BRCA2", "correct": false}], "correct_answer": "B. Rb, p53", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rb, p53 This patient has HPV infection , a dsDNA virus that causes anogenital warts as well as certain cancers like vaginal cancer and cervical cancer . HPV produces two proteins , namely E6 and E7 which are responsible for the loss of function mutation of p53 and Rb gene respectively . These two genes are tumor suppressor genes , so, their loss of function mutation results in an increased r isk of cancer . Hence, the correct answer is option B.</p>\n<p><strong>Highyeild:</strong></p><p>PAP smear is a screening test used to screen for cervical cancer and can also detect low-stage cervical intraepithelial neoplasia (CIN) . High-risk HPVs (16 and 18) are by far the most important factor in the development of cervical cancer. HPVs are DNA viruses. Sites in the female genital tract that are susceptible to infection include areas of squamous epithelial trauma and repair, where the virus may access basal cells, and the immature metaplastic squamous cells that are present at the squamocolumnar junction of the cervix Here, the viruses make factors that interfere with host proteins that regulate cell proliferation. The ability of HPV to act as a carcinogen depends on the viral E6 and E7 proteins , which interfere with the activity of the key tumor suppressor proteins , p53, and RB, respectively . MNEMONIC: E 6 goes with p 5 3 (5 and 6 go together).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. E6, E7, is incorrect because the question is asking about the genes and not the proteins . E6 and E7 are examples of proteins and not genes. Option:C. LMP1, and BCL2, are incorrect because LMP1 and BCL2 are the genes that are more commonly associated with Epstein Barr Virus . Option:D. BRCA1, BRCA2, is incorrect because BRCA1 and BRCA2 are the tumor suppressor genes that are more commonly associated with breast cancer .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 50-year-old woman presents with complaints of chronic cough, mucus-filled sputum, and weight loss in the last 3 months. She neither smokes nor drinks. CXR is done and it shows opacities in subpleural regions. A biopsy is done which reveals glands filled with mucin. A diagnosis of adenocarcinoma of the lung is made. The patient is at the highest risk of developing which complication?", "options": [{"label": "A", "text": "Hypertrophic osteoarthropathy", "correct": true}, {"label": "B", "text": "Cushing syndrome", "correct": false}, {"label": "C", "text": "SIADH", "correct": false}, {"label": "D", "text": "Polycythemia", "correct": false}], "correct_answer": "A. Hypertrophic osteoarthropathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hypertrophic osteoarthropathy The case is of adenocarcinoma lung , which is a type of bronchogenic carcinoma . The question stem is asking about the paraneoplastic syndrome that is associated with this type of cancer. Adenocarcinoma lung is associated with hypertrophic osteoarthropathy and clubbing of fingers . Hence, the correct option is A.</p>\n<p><strong>Highyeild:</strong></p><p>Paraneoplastic syndrome: Some patients with cancer develop signs and symptoms that cannot readily be explained by the anatomic distribution of the tumor or by the elaboration of hormones indigenous to the tissue from which the tumor arose; these are known as paraneoplastic syndromes. Paraneoplastic Syndromes Clinical Syndromes Major Forms of Underlying Cancer Causal Mechanism Endocrinopathies Cushing syndrome Small cell carcinoma of lung Pancreatic carcinoma Neural tumors ACTH or ACTH-like substance Syndrome of inappropriate antidiuretic hormone secretion Small cell carcinoma of lung Intracranial neoplasms Antidiuretic hormone or atrial natriuretic hormones Hypercalcemia Squamous cell carcinoma of lung Breast carcinoma Renal carcinoma Adult T-cell leukemia/lymphoma Parathyroid hormone-related protein (PTHRP), TGF-α, TNF, IL-I Hypoglycemia Ovarian carcinoma Fibrosarcoma Other mesenchymal sarcomas Insulin or insulin-like substance Polycythemia Renal carcinoma Cerebellar hemangioma Hepatocellular carcinoma Erythropoietin Osteomalacia Phosphaturic mesenchymal tumor FGF-23 Nerve and Muscle Syndromes Myasthenia Bronchogenic carcinoma Thymic neoplasms Immunologic Disorders of the central and peripheral nervous systems Breast carcinoma Dermatologic Disorders Acanthosis nigricans Gastric carcinoma Lung carcinoma Uterine carcinoma Immunologic; secretion of epidermal growth factor Dermatomyositis Bronchogenic carcinoma Breast carcinoma Immunologic Osseous, Articular, and Soft Tissue Changes Hypertrophic osteoarthropathy and clubbing of the fingers Bronchogenic carcinoma Thymic neoplasms Unknown Vascular and Hematologic Changes Venous thrombosis (Trousseau phenomenon) Pancreatic carcinoma Bronchogenic carcinoma Other cancers Tumor products (mucins that activate clotting) Disseminated intravascular coagulation Acute promyelocytic leukemia Prostatic carcinoma Tumor products that activate clotting Nonbacterial thrombotic endocarditis Advanced cancers Hypercoagulability Red cell aplasia Thymic neoplasms Unknown Others Nephrotic syndrome Various cancers Tumor antigens, immune complexes</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Cushing syndrome, is incorrect because Cushing syndrome occurs due to increased release of ACTH and is usually associated with small cell carcinoma lung , pancreatic carcinoma , and neural tumors . Option: C. SIADH,is incorrect because SIADH occurs due to the release of excessive ADH and is associated with small cell carcinoma lung . Option: D. Polycythemia,is incorrect because Polycythemia occurs due to excess release of erythropoietin and is associated with renal cell carcinoma .</p>\n<p><strong>Table:</strong></p><p>Paraneoplastic syndromes: Selected Oncogenes, Their Mode of Activation,\nand Associated Human Tumors Category Proto-Oncogene Mode of Activation in Tumor Associated Human Tumor Growth Factors PDGF- β PDGFB Overexpression Astrocytoma Fibroblast growth factors HSTI FGF3 Overexpression Amplification Osteosarcoma Stomach cancer Bladder cancer Breast cancer Melanoma TGF-α TGFA Overexpression Astrocytomas HGF HGF Overexpression Hepatocellular carcinomas Thyroid cancer Growth Factor Receptors EGF-receptor family ERBBI (EGFR) ERBB2 (HER Mutation Amplification Adenocarcinoma of lung Breast\n carcinoma FMS-like tyrosine kinase 3 FLT3 Point mutation or small\n duplications Leukemia Receptor for neurotrophic\n factors RET Point mutation Multiple endocrine neoplasia\n 2A and B, familial medullary thyroid carcinomas PDGF receptor PDGFRB Amplification, translocation Gliomas, leukemias Receptor for KIT ligand KIT Point mutation Gastrointestinal stromal\n tumors, seminomas, leukemias ALK receptor ALK Translocation Point mutation Adenocarcinoma of lung,\n certain lymphomas Neuroblastoma Proteins Involved in Signal\n Transduction GTP-binding (G) proteins KRAS HRAS NRAS GNAQ GNAS Point mutation Point mutation Point mutation Point mutation Point mutation Colon, lung, and pancreatic\n tumors Bladder and kidney tumors Melanomas, hematologic\n malignancies Uveal melanoma Pituitary adenoma, other\n endocrine tumors Nonreceptor tyrosine kinase ABL Translocation Chronic myelogenous leukemia\n Acute lymphoblastic leukemia RAS signal transduction BRAF Point mutation Melanomas, leukemias, colon\n carcinoma, others Notch signal transduction NOTCHI Point mutation, translocation Leukemias, lymphomas, breast carcinoma JAK/STAT signal transduction JAK2 Point mutation, translocation Myeloproliferative disorders Acute lymphoblastic leukemia Nuclear Regulatory Proteins Transcriptional activators MYC NMYC Translocation Amplification Burkitt lymphoma Neuroblastoma Cell Cycle Regulators Cyclins CCNDI (cyclin DI) Translocation Amplification Mantle cell lymphoma, multiple\n myeloma Breast and esophageal cancers Cyclin-dependent kinase CDK4 Amplification or point\n mutation Glioblastoma, melanoma, sarcoma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The carbohydrate marker of recurrent breast cancer is?", "options": [{"label": "A", "text": "CA 15.3", "correct": true}, {"label": "B", "text": "CA 125", "correct": false}, {"label": "C", "text": "CEA", "correct": false}, {"label": "D", "text": "CA 19.9", "correct": false}], "correct_answer": "A. CA 15.3", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CA 15.3</p>\n<p><strong>Highyeild:</strong></p><p>Tumour markers: Biochemical assays for tumor-associated enzymes, hormones, and other tumor markers in the blood lack the sensitivity and specificity necessary to diagnose cancer ; however, in concert with other tests, they may contribute to the detection of cancer, and in many instances, they are useful in following a tumor’s response to therapy and in detecting tumor recurrence . Selected Tumor Markers Tumor Markers Tumor Types Hormones Human chorionic gonadotropin Trophoblastic tumors, nonseminomatous testicular tumors Calcitonin Medullary carcinoma of thyroid Catecholamine and metabolites Pheochromocytoma and related tumors Ectopic hormones Oncofetal Antigens α-Fetoprotein Liver cell cancer, nonseminomatous germ cell tumors of testis Carcinoembryonic antigen Carcinomas of the colon, pancreas, lung, stomach, and heart Lineage-Specific Proteins Immunoglobulins Multiple myeloma and other gammopathies Prostate-specific antigen and prostate-specific membrane antigen Prostate cancer Mucins and Other Glycoproteins CA-125 Ovarian cancer CA-19-9 Colon cancer, pancreatic cancer CA-15-3 Breast cancer Cell-Free DNA Markers EGFR mutants in serum Lung cancer TP53, APC, RAS mutants in stool and serum Colon cancer TP53, RAS mutants in stool and serum Pancreatic cancer TP53, RAS mutants in sputum and serum Lung cancer TP53 mutants in urine Bladder cancer</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. CA 125. Tumour marker for Ovarian Ca . Option: C. Tumour marker for carcinomas of the colon, pancreas, stomach, and breast . Option: D. CA 19.9. Tumour marker for Colon Ca, Pancreatic Ca .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following immunohistochemical markers is positive in neuroendocrine tumors?", "options": [{"label": "A", "text": "Cytokeratin", "correct": false}, {"label": "B", "text": "Synaptophysin", "correct": true}, {"label": "C", "text": "Calretinin", "correct": false}, {"label": "D", "text": "HMB-45", "correct": false}], "correct_answer": "B. Synaptophysin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Synaptophysin In the neuroendocrine tumor , the occurrence of neurosecretory granules , the expression of neuroendocrine markers such as chromogranin , synaptophysin , and CD5 6 , and the ability of some of these tumors to secrete hormones (e.g., parathormone-related protein, a cause of paraneoplastic hypercalcemia) suggest that this tumor originates from neuroendocrine progenitor cells. It forms the immunohistochemical basis for the tumor.</p>\n<p><strong>Highyeild:</strong></p><p>IHC staining Cytokeratin: Carcinoma Vimentin: Sarcoma Desmin: Rhabdomyosarcoma HMB-45: Melanoma S-100: Langerhans Cell Histiocytosis Synaptophysin: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca Chromogranin: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca Nonspecific Enolase: NeuroEndocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca CD 56: Neuroendocrine Tumours: Carcinoid, Pheochromocytoma, Small cell lung ca</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Cytokeratin. IHC for Carcinomas . Option: C. Calretinin. Selective marker to diagnose mesothelioma (pleural tumor of the lung). Option: D. HMB-45. IHC for Melanoma .</p>\n<p><strong>Extraedge:</strong></p><p>Uses of IHC: Categorization of undifferentiated malignant tumors: The presence of cytokeratins , detected by immunohistochemistry, points to an epithelial origin ( carcinoma ), whereas desmin is specific for neoplasms of muscle cell origin , and hematologic malignancies lack these cytoskeletal structures. Determination of site of origin of metastatic tumor: In cases in which the origin of the tumor is unknown , immunohistochemical detection of tissue-specific or organ-specific antigens in a biopsy specimen of the metastatic deposit can lead to the identification of the tumor source. Detection of molecules that have prognostic or therapeutic significance: Immunohistochemical detection of hormone (estrogen/progesterone) receptors in breast cancer cell s is of prognostic and therapeutic value because these cancers are susceptible to anti-estrogen therapy .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is False?", "options": [{"label": "A", "text": "Cancer cell metabolism showing high glucose uptake and increased conversion of glucose to lactate is known as the Warburg effect", "correct": false}, {"label": "B", "text": "PET scan is based on the Warburg effect", "correct": false}, {"label": "C", "text": "Receptor tyrosine kinase activity and MYC gene is involved", "correct": false}, {"label": "D", "text": "Shows anaerobic glycolysis", "correct": true}], "correct_answer": "D. Shows anaerobic glycolysis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Shows anaerobic glycolysis Cancer cells demonstrate a form of cellular metabolism that is characterized by high levels of glucose uptake and increased conversion of glucose to lactate (fermentation) via glycolytic pathway , even in the presence of ample oxygen , this phenomenon is called Warburg Effect aka Aerobic Glycolysis . Clinically, this ‘glucose hunger’ helps in visualizing tumors on Positron Emission Tomography (PET) , wherein the patients are injected with 18F-fluorodeoxyglucose , which is taken up preferentially by tumor cells and also actively dividing tissues such as bone marrow.</p>\n<p><strong>Highyeild:</strong></p><p>Warburg Effect: Warburg metabolism is not cancer-specific , it is a general property of growing cells and is seen with all normal embryonic tissues. It is important to understand that by using this aerobic fermentation aka Warburg glycolysis, cells generate less ATP , so one might wonder why cancer cells then rely on such an inefficient glycolysis instead of oxidative phosphorylation which produces around 36 ATPs compared to 4 made by Warburg glycolysis. This is because in Aerobic glycolysis (Warburg) rapidly dividing cells are provided with metabolic intermediates that are needed for the synthesis of cellular components ie intermediate components (DNA, RNA, Proteins, Lipids, Organelles, etc) which are required for the growth of any rapid dividing cells for it to divide into daughter cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Cancer cell metabolism showing high glucose uptake and increased conversion of glucose to lactate is known as the Warburg effect. True . Option: B. PET scan is based on the Warburg effect. True . Option: C. Receptor tyrosine kinase activity and MYC gene is involved. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 22 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The best-suited anticoagulant for osmotic fragility test is:", "options": [{"label": "A", "text": "Heparin", "correct": true}, {"label": "B", "text": "EDTA", "correct": false}, {"label": "C", "text": "Trisodium citrate", "correct": false}, {"label": "D", "text": "Potassium oxalate", "correct": false}], "correct_answer": "A. Heparin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Heparin Best suited anticoagulant for the osmotic fragility test is Heparin . Heparinized venous blood or defibrinated blood may also be used Oxalated or citrated blood is not suitable because of the additional salts added to it .</p>\n<p><strong>Highyeild:</strong></p><p>Vacutainer tubes: Colours, anticoagulants and uses</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. EDTA. Incorrect . Option: C. Trisodium citrate. Incorrect . Option: D. Potassium oxalate. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>The sigmoid shape of the normal osmotic fragility curve indicates that normal red cells vary in their resistance to hypotonic solutions . Indeed, this resistance varies gradually (osmotically) as a function of red cell age, with the youngest cells being the most resistant and the oldest cells being the most fragile . The reason for this is that old cells have a higher sodium content and a decreased capacity to pump out sodium.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Direct coomb’s test positive is seen in all except:", "options": [{"label": "A", "text": "ABO incompatibility", "correct": false}, {"label": "B", "text": "Hemolytic disease of newborn", "correct": false}, {"label": "C", "text": "Aplastic anemia", "correct": true}, {"label": "D", "text": "Autoimmune hemolysis", "correct": false}], "correct_answer": "C. Aplastic anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Aplastic anemia</p>\n<p><strong>Highyeild:</strong></p><p>Direct Coombs test, also known as Direct Antiglobulin Test (DAT) , is a laboratory test used to detect the presence of antibodies or complement proteins attached to the surface of red blood cells . A positive direct Coombs test indicates the presence of these antibodies or complements proteins. Direct Coombs test is commonly used in the diagnosis of autoimmune hemolytic anemia and hemolytic disease of the newborn. It can also be positive in ABO incompatibility , where the mother's blood type is incompatible with the baby's blood type, and in autoimmune hemolysis , where the body produces antibodies that attack its own red blood cells. However, the Direct Coombs test is typically negative in aplastic anemia , which is a disorder characterized by a decrease in the number of red blood cells, white blood cells, and platelets in the blood. Aplastic anemia is not caused by antibody-mediated destruction of red blood cells, so the Direct Coombs test is not helpful in its diagnosis. Coomb’s test is positive in Immune hemolytic anemia They can be of 2 types: Direct Coomb’s test - Detects Antibody on RBC Surface Indirect Coomb’s test - Detects Antibody in Serum</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. ABO incompatibility. Direct coomb’s test positive . Option: B. Hemolytic disease of the newborn. Direct coomb’s test positive . Option: D. Autoimmune hemolysis. Direct coomb’s test positive .</p>\n<p><strong>Extraedge:</strong></p><p>Major causes of aplastic anemia: Acquired Idiopathic Acquired stem cell defects Immune mediated Chemical Agents Dose related Alkylating agents Antimetabolites Benzene Chloramphenicol Inorganic arsenicals Idiosyncratic Chloramphenicol Phenylbutazone Organic arsenicals Methylphenylethylhydantoin Carbamazepine Penicillamine Gold salts Physical Agents Whole-body irradiation Viral infections Hepatitis (unknown virus) Cytomegalovirus infections Epstein-Barr virus infections Herpes zoster (varicella zoster) Inherited Fanconi anemia Telomerase defects</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What happens when normal erythrocytes (blood–group matched) are transfused into a patient with anemia secondary to an intracorpuscular defect?", "options": [{"label": "A", "text": "Donor cells are destroyed", "correct": false}, {"label": "B", "text": "Donor cells have normal survival", "correct": true}, {"label": "C", "text": "Depends on the severity of anemia", "correct": false}, {"label": "D", "text": "Depends on whether the donor cells are fresh or stored (older than a week)", "correct": false}], "correct_answer": "B. Donor cells have normal survival", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Donor cells have normal survival When normal erythrocytes that are blood-group matched are transfused into a patient with anemia secondary to an intracorpuscular defect, the donor cells will have normal survival . This is because the cause of anemia in intracorpuscular defects, such as sickle cell anemia or thalassemia, is not related to the destruction of erythrocytes, but rather to a problem with their production or structure . Therefore, the transfused normal erythrocytes should function normally in the recipient's body and provide the needed oxygen-carrying capacity. Option: B. \"Donor cells have normal survival\", is the correct answer This Question is based on the knowledge that in the intracorpuscular defect of RBCs the defect lies in the RBCs itself and not in spleen or vessels and so any erythrocytes (blood – group matched) that are transfused into a patient will not be destroyed.</p>\n<p><strong>Highyeild:</strong></p><p>Blood bag additives and shelf life: Blood bag additives Shelf life Acid Citrate Dextrose 21 days Citrate Phosphate Dextrose Adenine 35 days Saline Adenine Glucose Mannitol 45 days</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Donor cells are destroyed. Incorrect . Option: C. Depends on the severity of anemia. Incorrect . Option: D. Depends on whether the donor cells are fresh or stored (older than a week). Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hemolysis in G6PD (glucose 6 phosphate dehydrogenase) enzyme deficiency may occur with all of the following drugs except", "options": [{"label": "A", "text": "Primaquine", "correct": false}, {"label": "B", "text": "Phenacetin", "correct": false}, {"label": "C", "text": "Probenecid", "correct": false}, {"label": "D", "text": "Penicillin", "correct": true}], "correct_answer": "D. Penicillin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Penicillin Penicillin causes hemolysis by the mechanism of autoimmune hemolytic anemia and not G6PD deficiency mediated Drugs causing haemolysis in glucose- 6-phosphate deficiency Analgesics, such as: Aspirin Phenacetin (withdrawn in the UK) Antimalarials, such as: Primaquine Pyrimethamine Quinine Chloroquine Pamaquin Antibacterials, such as: Most sulphonamides Dapsone Nitrofurantoin Chloramphenicol Quinolones Miscellaneous drugs, such as: Vitamin K Probenecid Quinidine Dimercaprol Phenylhydrazine</p>\n<p><strong>Highyeild:</strong></p><p>G6PD deficiency Abnormalities in the hexose monophosphate (HMP) shunt or glutathione metabolism resulting from deficient or impaired enzyme function reduce the ability of red cells to protect themselves against oxidative injuries and lead to hemolysis . G6PD deficiency is a recessive X-linked trait, placing males at much higher risk for symptomatic disease . G6PD mutations cause protein misfolding and breakdown , making it easier for red blood cells to break. As red blood cells age , the G6PD variants become less effective at protecting against oxidative stress , making older cells more likely to break than younger ones. The episodic hemolysis that is characteristic of G6PD deficiency is caused by exposures that generate oxidant stress. The most common triggers are infections, drugs implicated are numerous, including antimalarials (e.g., primaquine and chloroquine), sulfonamides, nitrofurantoin , and others. The most frequently cited food is the fava bean, which generates oxidants when metabolized called “Favism” . When G6PD deficient RBCs are exposed to high levels of oxidants , reactive sulfhydryl groups on globin chains cross-link and form Heinz bodies , and dark inclusions are seen in stained red blood cells. These Heinz bodies can damage the red blood cell membrane and cause intravascular hemolysis or reduced red blood cell flexibility . As the damaged cells pass through the spleen , macrophages remove the Heinz bodies , resulting in some cells retaining a ‘bitten’ appearance or becoming spherocytes due to loss of membrane surface area . Both types of damaged cells are then removed by phagocytes. Glucose-6-phosphate dehydrogenase deficiency: effects of oxidant drug exposure (peripheral blood smear). Inset, Red cells with precipitates of denatured globin (Heinz bodies) revealed by supravital staining. As the splenic macrophages pluck out these inclusions, \"bite cells\" like the one in this smear are produced.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Primaquine. Causes hemolysis in patients with G6PD deficiency . Option: B. Phenacetin. Causes hemolysis in patients with G6PD deficiency . Option: C. Probenecid. Causes hemolysis in patients with G6PD deficiency .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In G6PD deficiency which cells are more prone for hemolysis:", "options": [{"label": "A", "text": "Older red cells", "correct": true}, {"label": "B", "text": "Young red cells", "correct": false}, {"label": "C", "text": "Reticulocytes", "correct": false}, {"label": "D", "text": "All are susceptible", "correct": false}], "correct_answer": "A. Older red cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Older red cells Because mature red cells do not synthesize new proteins , G6PD− or G6PD Mediterranean enzyme activities fall quickly to levels inadequate to protect against oxidant stress as red cells age. Thus, older red cells are much more prone to hemolysis than younger ones.</p>\n<p><strong>Highyeild:</strong></p><p>G6PD deficiency Abnormalities in the hexose monophosphate (HMP) shunt or glutathione metabolism resulting from deficient or impaired enzyme function reduce the ability of red cells to protect themselves against oxidative injuries and lead to hemolysis . G6PD deficiency is a recessive X-linked trait, placing males at much higher risk for symptomatic disease . G6PD mutations cause protein misfolding and breakdown , making it easier for red blood cells to break. As red blood cells age , the G6PD variants become less effective at protecting against oxidative stress , making older cells more likely to break than younger ones. The episodic hemolysis that is characteristic of G6PD deficiency is caused by exposures that generate oxidant stress. The most common triggers are infections, drugs implicated are numerous, including antimalarials (eg: primaquine and chloroquine), sulfonamides, nitrofurantoin , and others. The most frequently cited food is the fava bean, which generates oxidants when metabolized called “Favism” . When G6PD deficient RBCs are exposed to high levels of oxidants , reactive sulfhydryl groups on globin chains cross-link and form Heinz bodies , and dark inclusions are seen in stained red blood cells. These Heinz bodies can damage the red blood cell membrane and cause Intravascular hemolysis or reduced red blood cell flexibility . As the damaged cells pass through the spleen , macrophages remove the Heinz bodies , resulting in some cells retaining a ‘bitten’ appearance or becoming spherocytes due to loss of membrane surface area . Both types of damaged cells are then removed by phagocytes. Glucose-6-phosphate dehydrogenase deficiency: effects of oxidant drug exposure (peripheral blood smear). Inset, Red cells with precipitates of denatured globin (Heinz bodies) revealed by supravital staining. As the splenic macrophages pluck out these inclusions, \"bite cells\" like the one in this smear are produced. (Courtesy Dr. Robert W. McKenna, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Young red cells. Incorrect . Option: C. Reticulocytes. Incorrect . Option: D. All are susceptible. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A most common mutation in hereditary spherocytosis:", "options": [{"label": "A", "text": "Spectrin", "correct": false}, {"label": "B", "text": "Ankyrin", "correct": true}, {"label": "C", "text": "Glycophorin A", "correct": false}, {"label": "D", "text": "Band 3", "correct": false}], "correct_answer": "B. Ankyrin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ankyrin</p>\n<p><strong>Highyeild:</strong></p><p>Most common mutation: Hereditary spherocytosis is Ankyrin > Band-3 > Spectrin Hereditary elliptocytosis is Spectrin Hereditary Spherocytosis: AD >> AR Defect: Ankyrin > Band-3 > Spectrin Maximum hemolysis is seen with: Loss of α Spectrin Peripheral smear: Spherocytes, Reticulocytosis Hereditary spherocytosis (peripheral smear). Note the anisocytosis and several dark-appearing spherocytes with no central pallor. Howell-Jolly bodies (small, dark nuclear remnants) also are seen in some of the red cells of this asplenic patient. Osmotic Fragility test: Fragility increased Coomb’s test: NEGATIVE Differentials: Immunohemolytic anemia Severe burns Toxins</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Spectrin. Incorrect . Option: C. Glycophorin A. Incorrect . Option: D. Band 3. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hemolytic crisis in hereditary spherocytosis is precipitated by", "options": [{"label": "A", "text": "Parvovirus B19 infection", "correct": true}, {"label": "B", "text": "Infectious mononucleosis", "correct": false}, {"label": "C", "text": "Human T-cell leukemia virus", "correct": false}, {"label": "D", "text": "Cytomegalovirus", "correct": false}], "correct_answer": "A. Parvovirus B19 infection", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Parvovirus B19 infection Hemolytic crises are produced by intercurrent events leading to increased splenic destruction of red cells . Aplastic/hypoplastic crisis resulting from parvovirus B19 infection may occur in Hereditary spherocytosis just as is seen in individuals with other chronic hemolytic disorders. Parvovirus B19 selectively infects erythroid precursors and inhibits their growth . Erythropoietic arrest leads to a sudden decrease in hemoglobin concentration and reticulocytopenia . The hemolytic crisis in hereditary spherocytosis is most commonly precipitated by viral infections , particularly Parvovirus B19 . Therefore, the correct answer is A. Although other viral infections such as infectious mononucleosis, cytomegalovirus, and human T-cell leukemia virus can also cause hemolytic crises in individuals with hereditary spherocytosis, they are less commonly associated with this condition compared to Parvovirus B19.</p>\n<p><strong>Highyeild:</strong></p><p>Hereditary Spherocytosis: AD >> AR Defect: Ankyrin > Band-3 > Spectrin Maximum hemolysis is seen with Loss of α Spectrin Peripheral smear: Spherocytes, Reticulocytosis Hereditary spherocytosis (peripheral smear). Note the anisocytosis and several dark-appearing spherocytes with no central pallor. Howell-Jolly bodies (small, dark nuclear remnants) also are seen in some of the red cells of this asplenic patient. Osmotic Fragility test: Fragility increased Coomb’s test: NEGATIVE Differentials: Immunohemolytic anemia Severe burns Toxins</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Infectious mononucleosis. Incorrect . Option: C. Human T-cell leukemia virus. Incorrect . Option: D. Cytomegalovirus. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Features of hemolytic anemia are all except:", "options": [{"label": "A", "text": "Hemoglobinemia", "correct": false}, {"label": "B", "text": "Bilirubinemia", "correct": false}, {"label": "C", "text": "Reticulocytosis", "correct": false}, {"label": "D", "text": "Haptoglobin increased", "correct": true}], "correct_answer": "D. Haptoglobin increased", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Haptoglobin increased</p>\n<p><strong>Highyeild:</strong></p><p>Features of Hemolytic Anemia: General examination Systemic examination Hemoglobin level MCV Reticulocytes Bilirubin LDH Haptoglobin Jaundice, pallor Splenomegaly; skeletal deformities (hemolytic facies) Q N/decreased Q Increased Increased Increased (mostly unconjugated) Q Increased decreased (if hemolysis is intravascular) Q</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hemoglobinemia. Seen in Hemolytic anemia . Option: B. Bilirubinemia. Seen in Hemolytic anemia . Option: C. Reticulocytosis. Seen in Hemolytic anemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In sickle cell anemia, all are seen except", "options": [{"label": "A", "text": "Sickle cells", "correct": false}, {"label": "B", "text": "Target cells", "correct": false}, {"label": "C", "text": "Howell jolly bodies", "correct": false}, {"label": "D", "text": "Ringed sideroblast", "correct": true}], "correct_answer": "D. Ringed sideroblast", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ringed sideroblast Ring sideroblasts are not seen in sickle cell anemia , but in Sideroblastic Anemia</p>\n<p><strong>Highyeild:</strong></p><p>Peripheral smear finding in sickle cell anemia : Ansiopoikilocytosis , polychromasia , Increased Retic % Irreversibly sickled RBC s and target cells (increased after auto splenectomy). Howell-Jolly bodies due to asplenia. Q Sickle cell disease (peripheral blood smear). (A) Low magnification shows irreversibly sickled cells as well as target cells and red cell anisocytosis and poikilocytosis. (B) Higher magnification shows an irreversibly sickled cell in the center.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Sickle cells. Seen . Option: B. Target cells. Seen . Option: D. Howell jolly bodies. Seen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A person having heterozygous sickle cell trait is protected from infection with –", "options": [{"label": "A", "text": "Plasmodium falciparum", "correct": true}, {"label": "B", "text": "P. vivax", "correct": false}, {"label": "C", "text": "Pneumococcus", "correct": false}, {"label": "D", "text": "Salmonella", "correct": false}], "correct_answer": "A. Plasmodium falciparum", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Plasmodium falciparum Person having heterozygous sickle cell trait is protected from infection of Plasmodium falciparum Mechanism by which patients with sickle cell trait are protected against Malaria: Preferential sickling of parasitized cells has been seen in the blood of children with sickle cell trait & malaria. Selective removal of sickled cells from the circulation probably reduces the degree of parasitemia and substantially limits the infectious process</p>\n<p><strong>Highyeild:</strong></p><p>Peripheral smear finding in sickle cell anemia : Ansiopoikilocytosis , polychromasia , Increased Retic % Irreversibly sickled RBC s and target cells (increased after auto splenectomy). Howell-Jolly bodies due to asplenia. Q Sickle cell disease (peripheral blood smear). (A) Low magnification shows irreversibly sickled cells as well as target cells and red cell anisocytosis and poikilocytosis. (B) Higher magnification shows an irreversibly sickled cell in the center.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. vivax. P. vivax enters red cells by binding to the Duffy blood group antigen , and most of the population of West Africa is not susceptible to infection by P. vivax because they do not have the Duffy antigen . Option: C. Pneumococcus. Incorrect . Option: D. Salmonella. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Severe Hereditary spherocytosis can be seen due to a defect of the following protein:", "options": [{"label": "A", "text": "α-Spectrin", "correct": true}, {"label": "B", "text": "Ankyrin", "correct": false}, {"label": "C", "text": "Band 3", "correct": false}, {"label": "D", "text": "Band 4.2", "correct": false}], "correct_answer": "A. α-Spectrin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>α-Spectrin Lifespan of RBC in Hereditary Spherocytosis is 20 days against a normal of 120 days Most common mutation in HS: Ankyrin > band 3 > α-Spectrin and band4.2 α-spectrin mutations (Autosomal recessive) leads to most severe phenotypes In Spectrin mutations, the most common RBC abnormality is Hereditary Elliptocytosis > spherocytosis</p>\n<p><strong>Highyeild:</strong></p><p>Hereditary Spherocytosis: AD >> AR Defect: Ankyrin > Band-3 > Spectrin Maximum hemolysis is seen with Loss of α Spectrin Peripheral smear: Spherocytes, Reticulocytosis Hereditary spherocytosis (peripheral smear). Note the anisocytosis and several dark-appearing spherocytes with no central pallor. Howell-Jolly bodies (small, dark nuclear remnants) also are seen in some of the red cells of this asplenic patient. Osmotic Fragility test: Fragility increased Coomb’s test: NEGATIVE</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Ankyrin. Incorrect . Option: C. Band 3. Incorrect . Option: D. Band 4.2. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Differentials: Immunohemolytic anemia Severe burns Toxins</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 16-year-old Afro-American boy presented with a non-healing ulcer of the foot with recurrent pneumonia, and chronic hemolytic anemia. The peripheral blood erythrocytes showed some RBCs with a peculiar appearance. The most likely cause is", "options": [{"label": "A", "text": "Point mutation", "correct": true}, {"label": "B", "text": "Intrinsic defects in the red cell membrane", "correct": false}, {"label": "C", "text": "Abnormalities in the hexose monophosphate shunt", "correct": false}, {"label": "D", "text": "Antibodies to RBCs", "correct": false}], "correct_answer": "A. Point mutation", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686829120039-QTDP072047IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Point mutation This is a case of a 16-year-old boy presenting with a foot ulcer, recurrent pneumonia, and chronic hemolytic anemia. This history of non-healing ulcers and repeated infection along with given peripheral smear findings is suggestive of Sickle cell anemia.</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. A point mutation in the 6th codon of β-globin leads to the replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Intrinsic defects in the red cell membrane. Seen with Hereditary Spherocytosis . Option: C. Abnormalities in the hexose monophosphate shunt. Seen with G6PD deficiency . Option: D. Antibodies to RBCs. Seen with Immunohemolytic anemia .</p>\n<p><strong>Table:</strong></p><p>Classification of Immunohemolytic anemia: Warm Antibody Type (IgG Antibodies Active at 37°C) Primary (idiopathic) Secondary Autoimmune\ndisorders (particularly systemic lupus erythematosus) Drugs Lymphoid\nneoplasms Cold Agglutinin Type (IgM Antibodies Active Below 37°C) Acute\n(mycoplasmal infection, infectious mononucleosis) Chronic Idiopathic Lymphoid\nneoplasms Cold Hemolysin Type (IgG Antibodies Active Below 37°C) Rare; occurs mainly in children following viral\ninfections</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Autosplenectomy is seen in:", "options": [{"label": "A", "text": "Hereditary spherocytosis", "correct": false}, {"label": "B", "text": "G6PD deficiency", "correct": false}, {"label": "C", "text": "Sickle cell anemia", "correct": true}, {"label": "D", "text": "Thalassemia major", "correct": false}], "correct_answer": "C. Sickle cell anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Sickle cell anemia Patients with sickle cell anemia may undergo auto splenectomy due to multiple infarcts in the splenic artery causing the spleen to be reduced to fibrous tissue (splenic atrophy spleen may become non-palpable).</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. A point mutation in the 6th codon of β-globin leads to the replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hereditary spherocytosis. Splenomegaly is seen which results from congestion of the cords of Billroth and increased numbers of phagocytes. Option: B. G6PD deficiency. Because hemolytic episodes related to G6PD deficiency occur intermittently, features related to chronic hemolysis (e.g., splenomegaly , cholelithiasis) are absent . Option: D. Thalassemia major. Splenomegaly is seen. Both phagocyte hyperplasia and extramedullary hematopoiesis contribute to the enlargement of the spleen.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False about Sickle cell anemia:", "options": [{"label": "A", "text": "Fetal Hb persists at high concentration in adult life as it is protective", "correct": false}, {"label": "B", "text": "Co-existing alpha thalassemia results in milder disease", "correct": false}, {"label": "C", "text": "Aplastic crisis is related to spleen", "correct": true}, {"label": "D", "text": "Sequestration crisis is related to spleen", "correct": false}], "correct_answer": "C. Aplastic crisis is related to spleen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Aplastic crisis is related to spleen Aplastic crisis is related to spleen: False , Aplastic crises stem from the infection of red cell progenitors by parvovirus B19, which causes a transient cessation of erythropoiesis and a sudden worsening of the anemia .</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. A point mutation in the 6th codon of β-globin leads to the replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fetal Hb persists at high concentration in adult life as it is protective. True , HbF has increased O2 affinity, thus it decreases sickling. Option: B. Co-existing alpha thalassemia results in milder disease. True , Co-existing alpha thalassemia reduces the amount of normal hemoglobin in individuals with sickle cell anemia. This can lead to a lower overall hemoglobin level, which can make the disease less severe by decreasing the tendency of red blood cells to sickle and reducing the risk of developing complications such as iron overload. Option: D. Sequestration crisis is related to the spleen. True , as it is due to hypersplenism. Massive entrapment of sickled red cells leads to rapid splenic enlargement, hypovolemia, and sometimes shock. Both sequestration crises and acute chest syndrome may be fatal and sometimes require prompt treatment with exchange transfusions.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is false about hemolytic anemia?", "options": [{"label": "A", "text": "Decreased LDH", "correct": true}, {"label": "B", "text": "Decreased Haptoglobin", "correct": false}, {"label": "C", "text": "Decreased RBC survival", "correct": false}, {"label": "D", "text": "Increased Unconjugated Bilirubin", "correct": false}], "correct_answer": "A. Decreased LDH", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Decreased LDH In hemolytic anemia, there is Increased LDH .</p>\n<p><strong>Highyeild:</strong></p><p>Features of Hemolytic Anemia: General examination Systemic examination Hemoglobin level MCV Reticulocytes Bilirubin LDH Haptoglobin Jaundice, pallor Splenomegaly; skeletal deformities (hemolytic facies) Q N/decreased Q Increased Increased Increased (mostly unconjugated) Q Increased decreased (if hemolysis is intravascular) Q</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Decreased Haptoglobin. Seen in Hemolytic anemia . Option: C. Decreased RBC survival. Seen in Hemolytic anemia . Option: D. Increased Unconjugated Bilirubin. Seen in Hemolytic anemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not true about Hereditary Spherocytosis?", "options": [{"label": "A", "text": "Extravascular hemolysis", "correct": false}, {"label": "B", "text": "Mutation in the protein of RBC membrane", "correct": false}, {"label": "C", "text": "Young RBCs are normal in shape", "correct": false}, {"label": "D", "text": "After splenectomy, Spherocytes disappear", "correct": true}], "correct_answer": "D. After splenectomy, Spherocytes disappear", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>After splenectomy, Spherocytes disappear After splenectomy, Spherocytes are still present , but hemolysis of these spherocytes in the spleen is prevented .</p>\n<p><strong>Highyeild:</strong></p><p>Hereditary Spherocytosis: AD >> AR Defect: Ankyrin > Band-3 > Spectrin Maximum hemolysis is seen with: Loss of α Spectrin Peripheral smear: Spherocytes, Reticulocytosis Hereditary spherocytosis (peripheral smear). Note the anisocytosis and several dark-appearing spherocytes with no central pallor. Howell-Jolly bodies (small, dark nuclear remnants) also are seen in some of the red cells of this asplenic patient. Osmotic Fragility test: Fragility increased Coomb’s test: NEGATIVE</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. True , as hemolysis occurs in spleen Option: B. True , as Spectrin/Ankyrin/Band-3 defect is seen in HS. Option: D. True , as RBCs get damaged & deformed in circulation</p>\n<p><strong>Extraedge:</strong></p><p>Differentials: Immunohemolytic anemia Severe burns Toxins</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is false about G6PD deficiency?", "options": [{"label": "A", "text": "X linked recessive", "correct": false}, {"label": "B", "text": "Young RBCs are more prone to hemolysis", "correct": true}, {"label": "C", "text": "Episodic hemolysis is seen", "correct": false}, {"label": "D", "text": "Both intravascular & extravascular hemolysis is seen", "correct": false}], "correct_answer": "B. Young RBCs are more prone to hemolysis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Young RBCs are more prone to hemolysis Rather younger RBCs are more resistant to hemolysis. Compared with the most common normal variant, G6PD B, the half-life of G6PD - is moderately reduced, whereas that of G6PD Mediterranean is more markedly abnormal. Because mature red cells do not synthesize new proteins, as red cells age G6PD - and G6PD Mediterranean enzyme activities quickly fall to levels that are inadequate to protect against oxidant stress. Thus, older red cells are much more prone to hemolysis than younger ones.</p>\n<p><strong>Highyeild:</strong></p><p>G6PD deficiency Abnormalities in the hexose monophosphate (HMP) shunt or glutathione metabolism resulting from deficient or impaired enzyme function reduce the ability of red cells to protect themselves against oxidative injuries and lead to hemolysis . G6PD deficiency is a recessive X-linked trait, placing males at much higher risk for symptomatic disease . G6PD mutations cause protein misfolding and breakdown , making it easier for red blood cells to break. As red blood cells age , the G6PD variants become less effective at protecting against oxidative stress , making older cells more likely to break than younger ones. The episodic hemolysis that is characteristic of G6PD deficiency is caused by exposures that generate oxidant stress. The most common triggers are infections, drugs implicated are numerous, including antimalarials (eg: primaquine and chloroquine), sulfonamides, nitrofurantoin , and others. The most frequently cited food is the fava bean, which generates oxidants when metabolized called “Favism” . When G6PD deficient RBCs are exposed to high levels of oxidants , reactive sulfhydryl groups on globin chains cross-link and form Heinz bodies , and dark inclusions are seen in stained red blood cells. These Heinz bodies can damage the red blood cell membrane and cause Intravascular hemolysis or reduced red blood cell flexibility . As the damaged cells pass through the spleen , macrophages remove the Heinz bodies , resulting in some cells retaining a ‘bitten’ appearance or becoming spherocytes due to loss of membrane surface area . Both types of damaged cells are then removed by phagocytes. Glucose-6-phosphate dehydrogenase deficiency: effects of oxidant drug exposure (peripheral blood smear). Inset, Red cells with precipitates of denatured globin (Heinz bodies) revealed by supravital staining. As the splenic macrophages pluck out these inclusions, \"bite cells\" like the one in this smear are produced.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. X linked recessive. True , it has X linked recessive inheritance . Option: C. Episodic hemolysis. True , as it occurs only when exposed to inciting factors like infection & certain drugs . Option: D. Both intravascular & extravascular hemolysis is seen, True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 23-year-old female presented with jaundice and pallor for 2 months. Her peripheral blood smear shows the presence of spherocytes. The most relevant investigation to arrive at a diagnosis is:", "options": [{"label": "A", "text": "Reticulocyte count", "correct": false}, {"label": "B", "text": "Osmotic fragility test", "correct": false}, {"label": "C", "text": "Coombs test", "correct": true}, {"label": "D", "text": "Tests for PNH", "correct": false}], "correct_answer": "C. Coombs test", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Coombs test Immunohemolytic anemia: Immunohemolytic anemia is caused by antibodies that recognize red cells and lead to their premature destruction . Antibody binding results in either red cell opsonization and extravascular hemolysis or ( uncommonly ) complement fixation and intravascular hemolysis . Classification of Immunohemolytic anemia: Warm Antibody Type (IgG Antibodies Active at 37°C) Primary (idiopathic) Secondary Autoimmune disorders (particularly systemic lupus erythematosus) Drugs Lymphoid neoplasms Cold Agglutinin Type (IgM Antibodies Active Below 37°C) Acute (mycoplasmal infection, infectious mononucleosis) Chronic Idiopathic Lymphoid neoplasms Cold Hemolysin Type (IgG Antibodies Active Below 37°C) Rare; occurs mainly in children following viral infections</p>\n<p><strong>Highyeild:</strong></p><p>Based on the information provided, the most relevant investigation to arrive at a diagnosis would be the Coombs test . The Coombs test is used to detect antibodies or complement proteins that are bound to red blood cells . It helps differentiate between immune-mediated hemolytic anemia and other causes of hemolysis . In this case, the presence of spherocytes on the peripheral blood smear suggests hemolytic anemia , where red blood cells are prematurely destroyed. The Coombs test can determine if the hemolysis is immune-mediated , meaning that it is caused by antibodies binding to the red blood cells. The diagnosis of immune hemolytic anemia requires the detection of antibodies and/or complement on red cells from the patient. This is done using the direct Coombs antiglobulin test , in which the patient’s red cells are mixed with sera-containing antibodies that are specific for human immunoglobulin or complement . If either immunoglobulin or complement is present on the surface of the red cells, the antibodies cause agglutination, which is appreciated visually as clumping .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Reticulocyte count. Tells only about increased erythropoiesis, seen with Hemolytic anemias . Option: B. Osmotic fragility test. Done for Hereditary Spherocytosis . Option: D. Tests for PNH. Flow cytometry shows the absence of CD55 and CD59 on the RBC surface .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 5-year-old male child presents with episodic jaundice and anemia since birth. Which of the following is least likely to be the diagnosis?", "options": [{"label": "A", "text": "Hereditary spherocytosis", "correct": false}, {"label": "B", "text": "Sickle cell disease", "correct": false}, {"label": "C", "text": "PNH", "correct": true}, {"label": "D", "text": "G6PD deficiency", "correct": false}], "correct_answer": "C. PNH", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PNH The given scenario is suggestive of episodes of hemolysis since birth , so it is probably due to a hereditary cause . Out of the given Option:s, Hereditary Spherocytosis, Sickle cell disease & G6PD deficiency are inherited causes of hemolytic anemia , so they are usually present in early childhood. PNH is due to an acquired somatic mutation in the PIG-A gene , which usually presents in adults. So, PNH is the least likely diagnosis in this cause. REMEMBER: Sickle cell disease usually presents beyond 6 months of age, due to high HbF concentration before that, which prevents sickling.</p>\n<p><strong>Highyeild:</strong></p><p>Paroxysmal Nocturnal Hemoglobinuria (PNH) Paroxysmal nocturnal hemoglobinuria (PNH) is a disease that results from acquired mutations in the phosphatidylinositol glycan complementation group A gene (PIGA), an enzyme that is essential for the synthesis of certain membrane-associated complement regulatory proteins. It is the only hemolytic anemia caused by an acquired genetic defect. PNH blood cells are deficient in three GPI-linked proteins that regulate complement activity: Decay-Accelerating Factor (DAF), or CD55 Membrane Inhibitor of Reactive Lysis (MIRL), or CD59 C8-binding protein Of these factors, the most important is CD59, a potent inhibitor of C3 convertase that prevents the spontaneous activation of the alternative complement pathway. Paroxysmal nocturnal hemoglobinuria (PNH). (A) Flow cytogram of blood from a normal individual shows that the red cells express two phosphatidylinositol glycan (PIG)-linked membrane proteins, CD55 and CD59, on their surfaces. (B) Flow cytogram of blood from a patient with PNH shows a population of red cells that is deficient in both CD55 and CD59. As is typical of PNH, a second population of CD55+/ CD59+ red cells that is derived from residual normal hematopoietic stem cells also is present. Red cells deficient in GPI-linked factors are abnormally susceptible to lysis or injury by complemen This manifests as intravascular hemolysis , which is caused by the C5b-C9 membrane attack complex . The tendency for red cells to lyse at night is explained by a slight decrease in blood pH during sleep, which increases the activity of complement. Thrombosis is the leading cause of disease-related death in individuals with PNH.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hereditary spherocytosis. That could be the diagnosis. Option: B. Sickle cell disease. That could be the diagnosis. Option: D. G6PD deficiency. That could be the diagnosis.</p>\n<p><strong>Extraedge:</strong></p><p>About 5% to 10% of patients eventually develop acute myeloid leukemia or a myelodysplastic syndrome , indicating that PNH may arise in the context of genetic damage to hematopoietic stem cells. PNH is diagnosed by flow cytometry , which provides a sensitive means for detecting red cells that are deficient in GPI-linked proteins such as CD59. Eculizumab , a monoclonal antibody, effectively blocks complement activation in PNH by preventing the conversion of C5 to C5a. This inhibition reduces hemolysis, lowers transfusion needs, and decreases thrombosis risk by up to 90%.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a patient suffering from sickle cell anemia, electrophoretic mobility of HbS in relation to HbA will be:", "options": [{"label": "A", "text": "Retarded", "correct": true}, {"label": "B", "text": "Accelerated", "correct": false}, {"label": "C", "text": "Same", "correct": false}, {"label": "D", "text": "Will depend upon concentrations of HbS", "correct": false}], "correct_answer": "A. Retarded", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Retarded Pathogenesis of Sickle cell anemia Sequence of codon 6 of the beta chain is changed from normal GAG to GTG resulting in the substitution of valine for glutamic acid . So, a charge of amino acid is changed from negatively charged ( glutamic acid ) to neutral amino acid ( Valine ). Thus in electrophoresis mobility of HbS will be lesser than HbA towards Anode (positive electrode) ie retarded mobility .</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. Point mutation in the 6th codon of β-globin that leads to replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Accelerated. Incorrect . Option: C. Same. Incorrect . Option: D. Will depend upon concentrations of HbS. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "25 y/o female came to OPD with anemia, jaundice, and joint pain. Which of the following statements is not true about condition?", "options": [{"label": "A", "text": "She can have pulmonary syndrome", "correct": false}, {"label": "B", "text": "She can have retinopathy", "correct": false}, {"label": "C", "text": "Hydroxyurea can help her", "correct": false}, {"label": "D", "text": "HbF and HbA2 will be undetectable", "correct": true}], "correct_answer": "D. HbF and HbA2 will be undetectable", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686829120506-QTDP072063IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>HbF and HbA2 will be undetectable The given peripheral blood picture shows sickle cells . HPLC diagnosis suggests increase in HbS, HbA2, and HbF while Hb A is decreased . Pulmonary syndrome & retinopathy are complications of Vaso-occlusive crises . Hydroxyurea increases HbF levels and so is used for treatment .</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. Point mutation in the 6th codon of β-globin that leads to replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. She can have the pulmonary syndrome. True . Option: B. She can have retinopathy. True . Option: C. Hydroxyurea can help her. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In sickle cell anemia, the defect is in which chain?", "options": [{"label": "A", "text": "α-chain", "correct": false}, {"label": "B", "text": "β-chain", "correct": true}, {"label": "C", "text": "Both the chains", "correct": false}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "B. β-chain", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>β-chain In sickle cell anemia defect is: a point mutation in the 6th codon of β-globin that leads to the replacement of a glutamate residue with a valine residue . Leading to: Abnormal physiochemical properties (Solubility defect) of the resulting sickle hemoglobin (HbS) Promotes the polymerization of deoxygenated hemoglobin Leading to red cell distortion Hemolytic anemia, microvascular obstruction, and ischemic tissue damage</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. Point mutation in the 6th codon of β-globin that leads to replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. α-chain. False . Option: C. Both the chains. False . Option: D. None of these. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In sickle cell trait, a number of bands found in Hb electrophoresis is:", "options": [{"label": "A", "text": "2", "correct": true}, {"label": "B", "text": "1", "correct": false}, {"label": "C", "text": "4", "correct": false}, {"label": "D", "text": "5", "correct": false}], "correct_answer": "A. 2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>2 In individuals with sickle cell trait , the number of bands found in hemoglobin (Hb) electrophoresis is typically two. The two bands represent the different types of hemoglobin present in the individual's blood. One band corresponds to hemoglobin A ( HbA ), which is the normal adult hemoglobin, and the other band corresponds to hemoglobin S ( HbS ), which is the abnormal hemoglobin associated with sickle cell trait, with HbA > HbS . Therefore, the correct answer is A. 2. Homozygous SS results in a single electrophoretic band at the S region . A positive test requires hemoglobin electrophoresis to distinguish the heterozygous from the homozygous state.</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. Point mutation in the 6th codon of β-globin that leads to replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A 2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. 1. False . Option: C. 4. False . Option: D. 5. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A man presents with fatigue. A Hemogram analysis suggested low Hb, and high MCV. The next investigation is:", "options": [{"label": "A", "text": "Vit B12/folate levels", "correct": false}, {"label": "B", "text": "Bone Marrow", "correct": false}, {"label": "C", "text": "S. Iron studies", "correct": false}, {"label": "D", "text": "Reticulocyte count", "correct": true}], "correct_answer": "D. Reticulocyte count", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reticulocyte count This is a tricky question as the initial investigation looks like B12/ folate levels , as the patient has macrocytosis . But remember, Macrocytosis can also be seen in Hemolytic anemia , as newer RBC precursors released are larger in size . So the initial investigation should be reticulocyte count .</p>\n<p><strong>Highyeild:</strong></p><p>Reticulocytes are juvenile red cells ; they contain remnants of the ribosomal ribonucleic acid (rRNA) that was present in larger amounts in the cytoplasm of the nucleated precursors from which they were derived. The number of reticulocytes in the peripheral blood is a fairly accurate reflection of erythropoietic activity . The cardinal signs of hemolysis in adults include anemia, jaundice, and reticulocytosis . The clinical and laboratory associations of increased hemolysis reflect the nature of the hemolytic mechanism, where the hemolysis is taking place, and the response of the bone marrow to the resultant anemia, namely erythroid hyperplasia, and reticulocytosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Vit B12/folate levels. Incorrect . Option: B. Bone Marrow. Incorrect . Option: C. S. Iron studies. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Prominent reticulocytosis is a feature of:", "options": [{"label": "A", "text": "Aplastic Anemia", "correct": false}, {"label": "B", "text": "Hemolytic Anemia", "correct": true}, {"label": "C", "text": "Nutritional Anemia", "correct": false}, {"label": "D", "text": "Anemia of chronic disease", "correct": false}], "correct_answer": "B. Hemolytic Anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemolytic Anemia Prominent reticulocytosis is a feature of Hemolytic Anemia , while all others in the Option:s have normal/ low reticulocyte count. Features of Hemolytic Anemia: General examination Systemic examination Hemoglobin level MCV Reticulocytes Bilirubin LDH Haptoglobin Jaundice, pallor Splenomegaly; skeletal deformities (hemolytic facies) Q N/decreased Q Increased Increased Increased (mostly unconjugated) Q Increased decreased (if hemolysis is intravascular) Q</p>\n<p><strong>Highyeild:</strong></p><p>Reticulocytes are juvenile red cells ; they contain remnants of the ribosomal ribonucleic acid (rRNA) that was present in larger amounts in the cytoplasm of the nucleated precursors from which they were derived. The number of reticulocytes in the peripheral blood is a fairly accurate reflection of erythropoietic activity . The cardinal signs of hemolysis in adults include anemia, jaundice, and reticulocytosis . The clinical and laboratory associations of increased hemolysis reflect the nature of the hemolytic mechanism, where the hemolysis is taking place, and the response of the bone marrow to the resultant anemia, namely erythroid hyperplasia, and reticulocytosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Aplastic Anemia. Low reticulocyte count . Option: C. Nutritional Anemia. Low reticulocyte count . Option: D. Anemia of chronic disease. Low reticulocyte count .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 35 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which is the most common benign tumor of the liver?", "options": [{"label": "A", "text": "leiomyoma", "correct": false}, {"label": "B", "text": "Lipoma", "correct": false}, {"label": "C", "text": "Hemangioma", "correct": true}, {"label": "D", "text": "Fibroma", "correct": false}], "correct_answer": "C. Hemangioma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemangioma Hepatic Hemangioma aka Cavernous hemangiomas, is the most common benign tumor of the liver.</p>\n<p><strong>Highyeild:</strong></p><p>Hepatic Hemangioma It is a venous malformation . Age: 30-50 years A biopsy is contraindicated because of the risk of hemorrhage. IOC: CECT - Three phases Non-contrast phase: Hypodense Arterial phase: Peripheral nodular enhancement Washout phase: Homogenous enhancement</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Leiomyoma: It is a benign tumor of smooth muscle cells, which is more commonly found in the uterus and gastrointestinal tract, but it can occur in the liver but is not the most common. Option: B. Lipoma: It is a benign tumor of fat cells Option: D. Fibroma: It is a benign tumor composed of fibrous tissue, which can occur in various parts of the body, including the liver. But it is uncommon in the liver.</p>\n<p><strong>Extraedge:</strong></p><p>Kasabach-Merritt syndrome It refers to consumption coagulopathy (consumes all platelets) which sometimes develops in a very large hepatic hemangioma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding hepatoblastoma except:", "options": [{"label": "A", "text": "It is a type of small round-cell tumor", "correct": false}, {"label": "B", "text": "It is the most common liver tumor in early childhood", "correct": false}, {"label": "C", "text": "FOX p3 gene mutation is most commonly seen", "correct": true}, {"label": "D", "text": "It may be associated with Beckwith-Wiedemann syndrome", "correct": false}], "correct_answer": "C. FOX p3 gene mutation is most commonly seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FOX p3 gene mutation is most commonly seen The genetic mutations commonly seen in hepatoblastoma involve the Wnt signaling pathway, such as CTNNB1 and WTX mutations , not FOX p3 gene mutation .</p>\n<p><strong>Highyeild:</strong></p><p>It is a small round-cell malignant liver tumor primarily affecting infants and young children. Tumor marker: AFP , Can also secrete beta-hCG Origin: Immature liver precursor cells Genetics: Loss of heterozygosity of the Chr. Arm 11p, Associated with Beckwith-wiedemann syndrome Diagnosis: Biopsy and Imaging</p>\n<p><strong>Extraedge:</strong></p><p>Beckwith-Widemann syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding hepatocellular carcinoma except:", "options": [{"label": "A", "text": "Alpha-1 antitrypsin deficiency is a risk factor", "correct": false}, {"label": "B", "text": "Intrahepatic metastasis occurs", "correct": false}, {"label": "C", "text": "Serum AFP levels are normal", "correct": true}, {"label": "D", "text": "Metastasis occurs via direct invasion, hematogenous or lymphatic route", "correct": false}], "correct_answer": "C. Serum AFP levels are normal", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serum AFP levels are normal Serum alpha-fetoprotein (AFP) levels are often elevated in patients with HCC , and AFP can be used as a diagnostic and prognostic marker for HCC.</p>\n<p><strong>Highyeild:</strong></p><p>Hepatocellular Carcinoma -Aka Hepatoma -It is the most common primary malignant liver tumor in adults Risk factors: Hepatitis B Hepatitis C Alcoholic and Non-alcoholic fatty liver disease Autoimmune disease Hemochromatosis Wilson disease Alpha-1 antitrypsin deficiency Thorotrast exposure Aflatoxin -Features: Anorexia, jaundice, tender hepatomegaly Decompensation of previously stable cirrhosis Portal vein thrombosis Metastasis: Direct invasion, hematogenous or lymphatic route</p>\n<p><strong>Table:</strong></p><p>Serum\n Tumor Markers Tumor Marker Associated Malignancy Alpha-fetoprotein (AFP) Hepatocellular carcinoma, Germ cell tumors Beta-human chorionic gonadotropin (beta-hCG) Germ cell tumors, Choriocarcinoma Cancer antigen 15-3 (CA 15-3) Breast cancer Cancer antigen 125 (CA 125) Epithelial ovarian cancer Cancer antigen 19-9 (CA 19-9) Pancreatic cancer, Cholangiocarcinoma Carcinoembryonic antigen (CEA) Colorectal cancer, Gastric cancer, Pancreatic cancer Prostate-specific antigen (PSA) Prostate cancer</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old patient, a chronic alcoholic presented with a history of weight loss, and jaundice. A liver biopsy is done and the image is shown below. Based on histological features, what is your diagnosis?", "options": [{"label": "A", "text": "Cirrhosis", "correct": false}, {"label": "B", "text": "Hepatocellular carcinoma", "correct": true}, {"label": "C", "text": "Cholangiocarcinoma", "correct": false}, {"label": "D", "text": "Lymphoma", "correct": false}], "correct_answer": "B. Hepatocellular carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689158017772-QTDP124005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hepatocellular carcinoma The given clinical scenario and a histopathological image showing nests of hepatocytes with nuclear atypia are suggestive of Hepatocellular carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Hepatocellular Carcinoma Aka Hepatoma It is the most common primary malignant liver tumor in adults Risk factors: Hepatitis B Hepatitis C Alcoholic and Non-alcoholic fatty liver disease Autoimmune disease Hemochromatosis Wilson disease Alpha-1 antitrypsin deficiency Thorotrast exposure Aflatoxin -Features: Anorexia, jaundice, tender hepatomegaly Decompensation of previously stable cirrhosis Portal vein thrombosis Metastasis: Direct invasion, hematogenous or lymphatic route</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Cirrhosis: It is a chronic liver disease characterized by fibrosis and nodular regeneration, which is a risk factor for the development of HCC. Option: C. Cholangiocarcinoma: It is a malignancy of the bile ducts, and its histological features are different from HCC. Option: D. Lymphoma: It is a malignancy of lymphoid cells, and it does not typically involve the liver as a primary site.</p>\n<p><strong>Table:</strong></p><p>Histopathology of Hepatocellular carcinoma Gross appearance: Well-circumscribed mass that appears\n tan-yellow to green Areas of hemorrhage and necrosis are\n common Solitary or multiple discrete nodules Background liver is usually cirrhotic Microscopic findings: Polygonal cells with nuclear atypia Cytoplasm varies from clear to eosinophilic Mallory-Denk bodies ,\n hyaline bodies, and pale bodies may be seen 4 principal growth patterns, including trabecular, pseudo\n glandular, solid and microtrabecular</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 65-year-old patient, who is a chronic alcoholic presented with a history of weight loss, jaundice and massive ascites, and further deteriorating condition. A liver biopsy is shown below based on histological features what is your diagnosis?", "options": [{"label": "A", "text": "Cirrhosis", "correct": true}, {"label": "B", "text": "Hepatocellular carcinoma", "correct": false}, {"label": "C", "text": "Cholangiocarcinoma", "correct": false}, {"label": "D", "text": "Lymphoma", "correct": false}], "correct_answer": "A. Cirrhosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689158021212-QTDP124006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cirrhosis The given clinical history of chronic alcoholism and histological features of fibrosis suggests the diagnosis of Cirrhosis . Cirrhosis is characterized by the development of fibrosis and the disruption of normal liver architecture. Alcoholic hepatitis is often accompanied by prominent activation of sinusoidal stellate cells and portal fibroblasts, giving rise to fibrosis.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological findings in Liver cirrhosis: Fibrosis : Deposition of collagen fibers and other extracellular matrix components in the liver, leading to the formation of fibrous tissue. It can be-portal fibrosis, perisinusoidal fibrosis, or bridging fibrosis. Nodules : The fibrosis can lead to the formation of nodules, which are groups of hepatocytes surrounded by fibrous tissue. The remaining hepatocytes may undergo proliferative changes, leading to the formation of regenerative nodules. Inflammation : Lymphocytes, plasma cells, and macrophages, can be seen in the liver tissue, particularly in the areas of active fibrosis. Distorted architecture : The liver architecture is disrupted, and the normal lobular structure is lost. Hepatocyte damage : Hepatocytes may show signs of degeneration, necrosis, or apoptosis, which can lead to the loss of liver function. Cholestasis : The bile ducts may become damaged or blocked, leading to cholestasis, which is the accumulation of bile acids and bilirubin in the liver tissue and blood. This can cause jaundice and itching.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B . Hepatocellular carcinoma: It is a type of primary liver cancer that can develop in patients with cirrhosis. Option: C. Cholangiocarcinoma: It is a type of cancer that develops in the bile ducts, and it is not commonly associated with chronic alcoholism as the primary etiology. Option: D. Lymphoma: a group of blood and lymph tumors that develop from lymphocytes.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding the fibrolamellar variant of HCC?", "options": [{"label": "A", "text": "Occurs typically in old patients", "correct": false}, {"label": "B", "text": "AFP is the tumor marker", "correct": false}, {"label": "C", "text": "No association with cirrhosis", "correct": true}, {"label": "D", "text": "Common in males", "correct": false}], "correct_answer": "C. No association with cirrhosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>No association with cirrhosis Fibrolamellar carcinoma is a distinctive variant of HCC which do not have an association with cirrhosis, alcoholism, or hepatitis B/C infection.</p>\n<p><strong>Highyeild:</strong></p><p>Fibrolamellar HCC Young patients Males = Females In non-cirrhotic liver The alpha-fetoprotein level is normal Tumor marker: Neurotensin B HPE: The tumor cells are arranged in cords that are separated by sheet-like fibrous bands arranged in a parallel or lamellar distribution</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It often occurs in young adults Option: B. Fibrolamellar HCC often does not produce alpha-fetoprotein (AFP). Option: D. It does not show any gender predilection</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "EBV is not associated with:", "options": [{"label": "A", "text": "Lymphocyte-predominant Hodgkin Lymphoma", "correct": true}, {"label": "B", "text": "Plasmablastic lymphoma", "correct": false}, {"label": "C", "text": "Nasopharyngeal Ca", "correct": false}, {"label": "D", "text": "Mixed cellularity Hodgkin’s Lymphoma", "correct": false}], "correct_answer": "A. Lymphocyte-predominant Hodgkin Lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphocyte-predominant Hodgkin Lymphoma EBV is associated with Plasmablastic lymphoma , Nasopharyngeal carcinoma & Mixed cellularity Hodgkin disease.</p>\n<p><strong>Highyeild:</strong></p><p>Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma . Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Plasmablastic lymphoma. Associated with EBV . Option: C. Nasopharyngeal Ca. Associated with EBV . Option: D. Mixed cellularity Hodgkin’s Lymphoma. Associated with EBV .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old female presents with cervical and axillary lymphadenopathy. There is a history of fever and drenching night sweats. She is diagnosed to have Hodgkin's lymphoma. What is the stage of the disease?", "options": [{"label": "A", "text": "II-A", "correct": false}, {"label": "B", "text": "II-B", "correct": true}, {"label": "C", "text": "IIE-A", "correct": false}, {"label": "D", "text": "IIE-B", "correct": false}], "correct_answer": "B. II-B", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>II-B Involvement of two or more lymph node regions on the same side of the diaphragm alone (II) or localized involvement of an extra-lymphatic organ or site (IIE). Presence of (B) symptoms : Unexplained fever, Drenching night sweats, and/or Unexplained weight loss > 10%</p>\n<p><strong>Highyeild:</strong></p><p>Clinical staging of Hodgkin and Non-Hodgkin’s Lymphoma: Stage Distribution of Disease I Involvement of a single lymph node region (1) or a single extralymphatic organ or site (IE) II Involvement of two or more lymph node regions on the same side of the diaphragm alone (II) or localized involvement of an extralymphatic organ or site (IIE) III Involvement of lymph node regions on both sides of the diaphragm without (III) or with (IIIE) localized involvement of an extralymphatic organ or site IV Diffuse involvement of one or more extralymphatic organs or sites with or without lymphatic involvement All stages are further divided on the basis of the absence (A) or presence (B) of the following symptoms: unexplained fever, drenching night sweats, and/or unexplained weight loss of greater than 10% of normal body weight.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. II-A. Incorrect . Option: C. IIE-A. Incorrect . Option: D. IIE-B. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Choose the FALSE statement regarding Hodgkin’s lymphoma:", "options": [{"label": "A", "text": "Affected lymph nodes become painful with alcohol ingestion", "correct": false}, {"label": "B", "text": "Ann Arbor Stage II is the involvement of two or more lymph node groups on both sides of the diaphragm", "correct": true}, {"label": "C", "text": "‘B symptoms’ are fever, night sweats and ≥ 10% weight loss in 6 months", "correct": false}, {"label": "D", "text": "ABVD regimen is the standard line of treatment", "correct": false}], "correct_answer": "B. Ann Arbor Stage II is the involvement of two or more lymph node groups on both sides of the diaphragm", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ann Arbor Stage II is the involvement of two or more lymph node groups on both sides of the diaphragm False, Ann Arbor Stage II is the involvement of two or more lymph node groups on the same side of the diaphragm .</p>\n<p><strong>Highyeild:</strong></p><p>Clinical staging of Hodgkin and Non-Hodgkin’s Lymphoma: Stage Distribution of Disease I Involvement of a single lymph node region (1) or a single extralymphatic organ or site (IE) II Involvement of two or more lymph node regions on the same side of the diaphragm alone (II) or localized involvement of an extralymphatic organ or site (IIE) III Involvement of lymph node regions on both sides of the diaphragm without (III) or with (IIIE) localized involvement of an extralymphatic organ or site IV Diffuse involvement of one or more extralymphatic organs or sites with or without lymphatic involvement All stages are further divided on the basis of the absence (A) or presence (B) of the following symptoms: unexplained fever, drenching night sweats, and/or unexplained weight loss of greater than 10% of normal body weight.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Affected lymph nodes become painful with alcohol ingestion: True Option: C. ‘B symptoms’ are fever, night sweats and ≥ 10% weight loss in 6 months: TRUE Option: D. ABVD regimen is the standard line of treatment for Hodgkin’s disease: True , AVBD is an abbreviation for a chemotherapy combination used to treat Hodgkin lymphoma. It includes the drugs doxorubicin hydrochloride (Adriamycin) , Vinblastine sulfate , Bleomycin sulfate , and Dacarbazine .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A person is having painless lymphadenopathy. On biopsy, binucleated owl-shaped nuclei with a clear vacuolated area are seen. On 35-year-old chemistry (IHC) CD 15 and CD 30 were positive. What is the most probable diagnosis?", "options": [{"label": "A", "text": "Nodular sclerosis", "correct": true}, {"label": "B", "text": "Mixed cellularity", "correct": false}, {"label": "C", "text": "Lymphocyte depletion type", "correct": false}, {"label": "D", "text": "Lymphocyte predominant Hodgkin’s Lymphoma", "correct": false}], "correct_answer": "A. Nodular sclerosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nodular sclerosis Binucleated owl-shaped nuclei with clear vacuolated area refers to as Lacunar cells . Lacunar cells are seen in the Nodular Sclerosis subtype of Hodgkin’s disease Lacunar cells have delicate, folded, or multilobate nuclei and abundant pale cytoplasm that is often disrupted during the cutting of sections, leaving the nucleus sitting in an empty space (lacuna) .</p>\n<p><strong>Highyeild:</strong></p><p>Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma . Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Mixed Cellularity. Microscopy: Mononuclear variants of RS cells . Option: C. Lymphocyte depletion type. Microscopy: Pleomorphic RS cells and Mummified RS cells . Option: D. Lymphocyte-predominant Hodgkin’s Lymphoma. CD15 and CD30 are negative . Microscopy: Popcorn RS cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False about nodular lymphocytic predominant Hodgkin’s lymphoma except:", "options": [{"label": "A", "text": "Consists predominantly of classical RS cells", "correct": false}, {"label": "B", "text": "CD 15 & CD 30 positive", "correct": false}, {"label": "C", "text": "Made up of T lymphocytes", "correct": false}, {"label": "D", "text": "EBV negative", "correct": true}], "correct_answer": "D. EBV negative", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>EBV negative Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma .</p>\n<p><strong>Highyeild:</strong></p><p>Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Consists predominantly of classical RS cells. False , popcorn cells are present. Option: B. CD 15 & CD 30 positive. False , it is CD 15 & CD 30 negative . Option: C. Made up of T lymphocytes. False , because both B & T lymphocytes, plasma cells & eosinophils are present .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which cell is not seen in Hodgkin lymphoma -", "options": [{"label": "A", "text": "Reed sternberg cell", "correct": false}, {"label": "B", "text": "Lacunar cell", "correct": false}, {"label": "C", "text": "L&H cell", "correct": false}, {"label": "D", "text": "Langerhan cell", "correct": true}], "correct_answer": "D. Langerhan cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Langerhan cell Langerhans cells are dendritic cells seen in the epidermis of the skin ; They act as Antigen-presenting cells . The neoplastic proliferation of Langerhans cells is seen in Langerhans cell Histiocytosis (LCH) . Reed Sternberg cell , Lacunar cell , L&H cell (Lymphocytic & Histiocytic variant of Reed- Sternberg cell) & Hodgkin cells are seen in Hodgkin’s disease.</p>\n<p><strong>Highyeild:</strong></p><p>Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma . Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Reed Sternberg cell. Seen in Hodgkin’s disease. Option: B. Lacunar cell. Seen in Hodgkin’s disease. Option: C. L&H cell. Seen in Hodgkin’s disease.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 10 yr old boy with a mass in the abdomen. On imaging, the paraaortic LN is enlarged. On biopsy, a starry sky appearance is seen. What is the underlying abnormality?", "options": [{"label": "A", "text": "p53 gene mutation", "correct": false}, {"label": "B", "text": "RB gene mutation", "correct": false}, {"label": "C", "text": "Translocation involving BCR-ABL genes", "correct": false}, {"label": "D", "text": "Translocation involving MYC gene", "correct": true}], "correct_answer": "D. Translocation involving MYC gene", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Translocation involving MYC gene Burkitt Lymphoma: Burkitt’s has a male predominance and is typically seen in patients <35 years of age . In Burkitt lymphoma , the tumour has a high mitotic index, and numerous apoptotic cells, combined with benign macrophages. Macrophages have abundant clear cytoplasm: a characteristic “ starry sky” pattern seen in Lymph Node biopsy. Mutation: C-MYC on Chromosome 8. t ( 8 ;14), t (2; 8 ), t ( 8 ;22). IHC: CD 10 +, CD19+, CD20+, and BCL6+, surface IgM+ Burkitt’s Lymphoma is the most common cause of tumour lysis syndrome .</p>\n<p><strong>Highyeild:</strong></p><p>Classification of Burkitt’s Lymphoma Endemic (in Africa) 80-90% association with EBV. Most common site: Mandible . Sporadic 20-30% association with EBV. Most common site: The ileocaecal region . HIV associated 30-40% association with EBV. Most common site: Lymph node .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. p53 gene mutation. Germline mutation causes Li Fraumeni syndrome . Option: B. RB gene mutation. The mutation causes Retinoblastoma . Option: C. Translocation involving BCR-ABL genes. Seen with CML , a history of the 50-60-year-old patient would be given with leukocytosis, shift to left and basophilia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements on lymphoma is not True-", "options": [{"label": "A", "text": "A single classification system for Hodgkin’s disease (HD) is almost universally accepted", "correct": false}, {"label": "B", "text": "HD more often tends to remain localized to a single group of lymph nodes and spreads by contiguity", "correct": false}, {"label": "C", "text": "Several types of non-Hodgkin’s lymphoma (NHL) may have a leukemic phase", "correct": false}, {"label": "D", "text": "In general follicular (nodular) NHL has a worse prognosis compared to diffuse NHL", "correct": true}], "correct_answer": "D. In general follicular (nodular) NHL has a worse prognosis compared to diffuse NHL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>In general follicular (nodular) NHL has a worse prognosis compared to diffuse NHL False, as Follicular Lymphoma is a low-grade Non-Hodgkin’s and has a better prognosis .</p>\n<p><strong>Highyeild:</strong></p><p>Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma . Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. A single classification system for Hodgkin’s disease (HD) is almost universally accepted. True, the Ann Arbor staging system is used Option: B. HD more often tends to remain localized to a single group of lymph nodes and spreads by contiguity. True, it spreads to anatomically adjacent lymph nodes Option: C. Several types of non-Hodgkin’s lymphoma (NHL) may have a leukemic phase. True, Lymphoma may spill over into peripheral blood causing Leukaemia like the picture.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Post-transplant lymphoma occurs due to the proliferation of which of the following cells -", "options": [{"label": "A", "text": "T cell", "correct": false}, {"label": "B", "text": "B cell", "correct": true}, {"label": "C", "text": "NK cell", "correct": false}, {"label": "D", "text": "Monocyte", "correct": false}], "correct_answer": "B. B cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B cell Post-transplant lymphoma (Post-transplant Lymphoproliferative Disorder or PTLD) occurs due to the proliferation of B cells , 90% being EBV positive .</p>\n<p><strong>Highyeild:</strong></p><p>Hodgkin’s Lymphoma: Arises from B cells of the Germinal centre region . Activation of transcription factor NF-κB is a common event in classical Hodgkin’s Lymphoma . Diagnosis of Hodgkin’s Lymphoma depends on the identification o f Reed Sternberg cells (RS cells) in a background of non-neoplasticism inflammatory cells . Classical Mixed cellularity Nodular sclerosis Lymphocyte rich Lymphocyte depleted Nodular Lymphocyte predominant Important points about Hodgkin’s Lymphoma: Mixed Cellularity: Most common Hodgkin’s Lymphoma in India. Associated with HIV and EBV. Males > Females. Constitutive or B symptoms are more common. Microscopy: Mononuclear variants of RS cells. Nodular Sclerosis: Most common Hodgkin’s Lymphoma in the world. 2nd best prognosis. Not associated with EBV. Females > Males. Microscopy: Lacunar variants and collagen bands were seen. Lymphocyte Rich: Seen in older males. Lymphocyte Depleted: Maximum EBV association. Worst prognosis. Microscopy: Pleomorphic RS cells and Mummified RS cells. Nodular Lymphocyte Predominant: Best prognosis. No EBV association. Microscopy: Popcorn RS cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. T cell. Incorrect . Option: C. NK cell. Incorrect . Option: D. Monocyte. Incorrect .</p>\n<p><strong>Table:</strong></p><p>Virus and associated malignancies: Infectious Agents Associated with the Development\n of Lymphoid Malignancies INFECTIOUS AGENT LYMPHOID MALIGNANCY Epstein-Barr virus Burkitt's lymphoma Post-organ transplant lymphoma Primary CNS diffuse large B-cell lymphoma Hodgkin's lymphoma Extranodal NK/T-cell lymphoma, nasal type HTLV-1 Adult T-cell leukemia/lymphoma HIV Diffuse large B-cell lymphoma Burkitt's lymphoma Hepatitis C virus Lymphoplasmacytic lymphoma Helicobacter pylori Gastric MALT lymphoma Human herpesvirus 8 Primary effusion lymphoma Multicentric Castleman's disease Abbreviations: CNS, central nervous system; HIV,\nhuman immunodeficiency virus; HTLV, human T cell lymphotropic virus; MALT,\nmucosa-associated lymphoid tissue; NK, natural killer</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 19 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 45-year-old man who works on a bird farm presents with recurrent episodes of cough, shortness of breath, and fever. His symptoms worsen during the workweek and improve over the weekend when he is away from work.CT scan of the chest shows ground-glass opacities All of the following statements are true regarding histological features of the diagnosis except?", "options": [{"label": "A", "text": "Interstitial pneumonitis", "correct": false}, {"label": "B", "text": "Noncaseating granuloma", "correct": false}, {"label": "C", "text": "Eosinophilic abscess", "correct": true}, {"label": "D", "text": "Interstitial fibrosis", "correct": false}], "correct_answer": "C. Eosinophilic abscess", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Eosinophilic abscess The given clinical scenario is suggestive of Hypersensitivity pneumonitis (HP). An eosinophilic abscess is not a typical feature of HP , and its presence should raise the possibility of other diagnoses, such as eosinophilic pneumonia or acute eosinophilic pneumonia.</p>\n<p><strong>Highyeild:</strong></p><p>Hypersensitivity pneumonitis (HP) It is a type of interstitial lung disease caused by repeated exposure to a variety of inhaled antigens, such as organic dust, fungi, bacteria, and animal proteins. HP is a type III and type IV hypersensitivity reactio n that involves an immune response to inhaled antigens, leading to inflammation and damage to the lung tissue. - Histological findings of Hypersensitivity pneumonitis: Interstitial pneumonitis: It is characterized by interstitial inflammation and cellular infiltration, which can lead to thickening of the alveolar walls and impaired gas exchange. Non-caseating granulomas: These are composed of epithelioid cells and giant cells and are typically located in the bronchioles, alveolar ducts, and surrounding interstitium. Bronchiolitis obliterans organizing pneumonia: BOOP is a pattern of lung injury characterized by the presence of loose granulation tissue and fibrosis within the alveolar ducts, bronchioles, and adjacent alveoli. Lymphocytic infiltrates: Within the interstitial tissue of the lung Fibrosis : Chronic HP can result in interstitial fibrosis due to the chronic inflammation and repair processes that can lead to remodeling of the lung architecture, impaired lung function, and respiratory failure. Absence of necrosis: Unlike other forms of interstitial lung disease, hypersensitivity pneumonitis is not associated with necrotizing granulomas or necrosis of lung tissue. Eosinophilic infiltrates</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B, D: Interstitial pneumonitis, non-caseating granulomas, and interstitial fibrosis are histopathological findings in Lung biopsy of Hypersensitivity pneumonitis.</p>\n<p><strong>Extraedge:</strong></p><p>Richerson’s classification of HP Classification Duration Features Acute HP Symptoms begin 2-9 h after exposure , peak typically between 6 and 23 h, and last from hours to days. ● Influenza-like symptoms often predominate chills, fever, sweating, myalgias, lassitude, headache, and nausea. ● Respiratory symptoms, such as cough and dyspnea, are common but not universal Subacute HP May appear gradually over several days to weeks ● Marked by cough and dyspnea, and may progress to severe dyspnea and cyanosis, leading to hospitalization. Chronic HP Insidious onset over a period of months ● Increasing cough and exertional dyspnea. Fatigue and weight loss may be prominent symptoms.</p>\n<p><strong>Table:</strong></p><p>Common types of Hypersensitivity Pneumonitis Disease Exposure Source Causative antigen Bird fancier's disease Various birds Protein in avian feces, feathers Cheese worker's lung Moldy cheese Penicillium species Farmer's lung Moldy hay Thermophilic actinomycetes Hot tub lung Warm water Mycobacterium avium complex Humidifier lung Warm water Thermophilic actinomycetes Japanese summer disease Moldy houses Various fungi Machine worker's lung Metal-cutting fluid Mycobacterium species, Gram-negative bacilli Malt worker's lung Moldy malt Aspergillus species Mushroom worker's lung Mushrooms Mushroom spores, various other fungi Chemical worker's lung Polyurethane foams, spray paints, dyes, glues,\n varnishes, lacquer Diisocyanates, toluene, trimellitic anhydride</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The most important cells in type I hypersensitivity:", "options": [{"label": "A", "text": "Macrophages", "correct": false}, {"label": "B", "text": "Mast cells", "correct": true}, {"label": "C", "text": "Neutrophils", "correct": false}, {"label": "D", "text": "Lymphocytes", "correct": false}], "correct_answer": "B. Mast cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mast cells In immediate hypersensitivity (type I hypersensitivity) , the injury is caused by T H2 cells , IgE antibodies , mast cells, and other leukocytes . Mast cells release mediators that act on vessels and smooth muscle and proinflammatory cytokines that recruit inflammatory cells</p>\n<p><strong>Highyeild:</strong></p><p>Immediate , or type I hypersensitivity is a rapid immunologic reaction occurring in a previously sensitized individual that is triggered by the binding of an antigen to IgE antibody on the surface of mast cells. These reactions are often called allergies , and the antigens that elicit them are allergens.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, C and D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A female presented with generalized edema sweating, flushing, tachycardia, and fever after a bee sting. This is an example of?", "options": [{"label": "A", "text": "T cell-mediated cytotoxicity", "correct": false}, {"label": "B", "text": "IgE-mediated reaction", "correct": true}, {"label": "C", "text": "IgG-mediated reaction", "correct": false}, {"label": "D", "text": "IgA-mediated hypersensitivity reaction", "correct": false}], "correct_answer": "B. IgE-mediated reaction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IgE-mediated reaction Many local type I hypersensitivity reactions have two well-defined phases : The immediate reaction is characterized by vasodilation, vascular leakage, and depending on the location, smooth muscle spasm or glandular secretions . Usually become evident within minutes after exposure to an allergen and tends to subside in a few hours . In many instances (e.g., allergic rhinitis and bronchial asthma), a second, late-phase reaction sets in 2 to 24 hours later without additional exposure to antigen and may last for several days. This late-phase reaction is characterized by infiltration of tissues with eosinophils, neutrophils, basophils, monocytes, and CD4+ T cells, as well as tissue destruction , typically in the form of mucosal epithelial cell damage. Most immediate hypersensitivity disorders are caused by excessive T H2 responses and these cells play a central role by stimulating IgE production and promoting inflammation.</p>\n<p><strong>Highyeild:</strong></p><p>Immediate , or type I hypersensitivity is a rapid immunologic reaction occurring in a previously sensitized individual that is triggered by the binding of an antigen to IgE antibody on the surface of mast cells. These reactions are often called allergies , and the antigens that elicit them are allergens.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, C and D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 26-year-old woman presents with a rash on sun-exposed areas, painless oral ulcers, and a malar rash on the nose. What is the most likely diagnosis?", "options": [{"label": "A", "text": "SLE", "correct": true}, {"label": "B", "text": "Dermatomyositis", "correct": false}, {"label": "C", "text": "Sarcoidosis", "correct": false}, {"label": "D", "text": "Systemic sclerosis", "correct": false}], "correct_answer": "A. SLE", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>SLE</p>\n<p><strong>Highyeild:</strong></p><p>SLE is an autoimmune disease involving multiple organs , characterized by a vast array of autoantibodies, particularly antinuclear antibodies (ANAs) , in which injury is caused mainly by the deposition of immune complexes and binding of antibodies to various cells and tissues . The hallmark of SLE is the production of autoantibodies, several of which (antibodies to double-stranded DNA and the so-called Smith [Sm] antigen ) are virtually diagnostic. Exposure to ultraviolet ( UV) light exacerbates the disease in many individuals . UV irradiation may induce apoptosis in cells and may alter the DNA in such a way that it becomes immunogenic, perhaps because of enhanced recognition by Toll-Like In addition, UV light may modulate the immune response, for example, by stimulating keratinocytes to produce IL-1, a cytokine known to promote inflammation.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Dermatomyositis , is a rare inflammatory disease. Common symptoms of dermatomyositis include a distinctive skin rash, muscle weakness, inflammatory myopathy, or inflamed muscles . Option: C. Sarcoidosis , is a multisystem inflammatory disease of unknown etiology that manifests as noncaseating granulomas, predominantly in the lungs and intrathoracic lymph nodes . Option: D. Systemic sclerosis , is a systemic connective tissue disease. Characteristics of systemic sclerosis include essential vasomotor disturbances; fibrosis, subsequent atrophy of the skin, subcutaneous tissue, muscles, and internal organs (eg, alimentary tract, lungs, heart, kidney, CNS) .</p>\n<p><strong>Extraedge:</strong></p><p>Revised Criteria for Classification of Systemic Lupus Erythematosus Criterion Definition Clinical Criteria Acute cutaneous lupus Malar rash (fixed erythema, flat or raised, over the malar eminences), photosensitivity Chronic cutaneous lupus Discoid rash: erythematous raised patches with adherent keratotic scaling and follicular plugging Nonscarring alopecia Diffuse thinning or hair fragility in the absence of other causes Oral or nasal ulcers Oral or nasopharyngeal ulceration, usually painless Joint disease Nonerosive synovitis involving two or more peripheral joints, characterized by tenderness, swelling, or effusion Serositis Pleuritis (pleuritic pain or rub or evidence of pleural effusion), pericarditis Renal disorder Persistent proteinuria >0.5 g/24 hours, or red cell casts Neurologic disorder Seizures, psychosis, myelitis, or neuropathy, in the absence of offending drugs or other known causes Hemolytic anemia Hemolytic anemia Leukopenia or lymphopenia Leukopenia: <4.0 x 10 9 cells/L (4000 cells/mm 3 ) total on two or more occasions, or Lymphopenia: <1.5 x 10 9 cells/L (1500 cells/mm³) on two or more occasions Thrombocytopenia Thrombocytopenia: <100 x 10 9 cells/L (100 x 10 cells/mm³) in the absence of offending drugs and other conditions Immunologic Criteria Antinuclear antibody (ANA) Abnormal titer of antinuclear antibody by immunofluorescence Anti-dsDNA antibody Abnormal titer Anti-Sm antibody Presence of antibody to Sm nuclear antigen Antiphospholipid antibody Positive finding of antiphospholipid antibodies based on (1) an abnormal serum level of IgG or IgM anti-cardiolipin antibodies, (2) a positive test for lupus anticoagulant using a standard test, or (3) a false-positive serologic test for syphilis known to be positive for at least 6 months and confirmed by negative Treponema pallidum immobilization or fluorescent treponemal antibody absorption test Low complement Low C3, C4, or CH50 Direct Coombs test Assay for anti-red cell antibody, in the absence of clinically evident hemolytic anemia \"This classification was initially proposed in 1997 by the American College of Rheumatology for the purpose of identifying patients in clinical studies. It was updated in 2012 by the Systemic Lupus International Collaborating Clinics. A patient is classified as having SLE if four of the clinical and immunologic criteria are present at any time (not necessarily concurrently), including at least one clinical and one immunologic criterion. Some details have been omitted from the table. Modified from Petri M. Orbai AM, Alarcón GS, et al: Derivation and validation of the Systemic Lupus International Collaborating Clinics classification criteria for systemic lupus erythematosus, Arthritis Rheum 64:2677, 2012.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 24-year-old female has a malar rash, Dermatitis on sun-exposed areas of skin, and joint pain. She also has tuberculosis for which she is taking rifampicin, ethambutol, isoniazid, and pyrazinamide. All are true, except:", "options": [{"label": "A", "text": "Anti Histone antibodies positive", "correct": false}, {"label": "B", "text": "Pyrazinamide is the cause of this condition", "correct": true}, {"label": "C", "text": "It can be cured by stopping the drugs which caused it", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. Pyrazinamide is the cause of this condition", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pyrazinamide is the cause of this condition</p>\n<p><strong>Highyeild:</strong></p><p>Drug-Induced Lupus Erythematosus: Based on history and symptoms diagnosis of Drug-induced SLE is made . In this case, Isoniazid is responsible , not pyrazinamide . Drug-induced lupus can affect people who take the culprit drugs for months or years continuously without symptoms. That's a clue that it's DIL instead of typical sid e effects because side effects usually come on soon after you start taking a new medication .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Anti Histone antibodies positive. True . Option: C. It can be cured by stopping the drugs which caused it. True . Option: D. All are true. Incorrect option .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 28-year-old female has muscle weakness mostly in the evening. She also has diplopia and ptosis on the right side and dysphagia. What is your diagnosis and which type of hypersensitivity reaction is responsible for this condition?", "options": [{"label": "A", "text": "Myasthenia gravis, Type 1 HSR", "correct": false}, {"label": "B", "text": "Myasthenia gravis, Type 2 HSR", "correct": true}, {"label": "C", "text": "Multiple sclerosis, Type 3 HSR", "correct": false}, {"label": "D", "text": "Multiple sclerosis, Type 4 HSR", "correct": false}], "correct_answer": "B. Myasthenia gravis, Type 2 HSR", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myasthenia gravis, Type 2 HSR</p>\n<p><strong>Highyeild:</strong></p><p>Myasthenia Gravis: From the given clinical data most likely diagnosis is Myasthenia gravis . Myasthenia gravis is an autoimmune disease that is usually associated with autoantibodies directed against acetylcholine receptors . About 85% of patients have autoantibodies against postsynaptic acetylcholine receptors , while most of the remaining patients have antibodies against the sarcolemmal protein muscle-specific receptor tyrosine kinase. Myasthenia is a type 2 HSR . Patients with anti-acetylcholine receptor antibodies are typically present with fluctuating weakness that worsens with exertion and often over the day . Diplopia and ptosis due to the involvement of extraocular muscles are common and distinguish myasthenia gravis from myopathies , in which the involvement of extraocular muscles is unusual. In some patients, symptoms are confined to ocular muscles called Ocular Myasthenia Gravis , while others develop generalized weakness that can be so severe as to require mechanical ventilation called Generalised Myasthenia .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Myasthenia gravis, Type 1 HSR. Myasthenia is a type 2 HSR . Option: C. Multiple sclerosis, Type 3 HSR. Multiple sclerosis is type 4 HSR and is not the diagnosis here . Option: D. Multiple sclerosis, Type 4 HSR. Multiple sclerosis is not the diagnosis here .</p>\n<p><strong>Extraedge:</strong></p><p>Myasthenia gravis Lambert Eaton syndrome Antibody against AchR antibody Antibody against voltage gated calcium channel Associated with Thymic tumor Associated with Small cell lung cancer Weakness worsen on prolonged exercise Weakness improves on prolonged exercise Normal Deep tendon reflex Decreased or absent deep tendon reflex Autonomic dysfunction is absent Autonomic dysfunction is present On repeated nerve stimulation, there is decremental response On repeated nerve stimulation, there is incremental response</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 56-year-old male diagnosed with lung cancer presents with complaints of limb muscle weakness, on repeated stimulus the weakness improves. What is the cause of this condition?", "options": [{"label": "A", "text": "Paraneoplastic syndrome due to antibodies formation against muscle spindles", "correct": false}, {"label": "B", "text": "Paraneoplastic syndrome due to antibodies formation against postsynaptic acetylcholine receptors", "correct": false}, {"label": "C", "text": "Paraneoplastic syndrome due to antibodies formation against presynaptic calcium receptors", "correct": true}, {"label": "D", "text": "Metastasis of lung cancer", "correct": false}], "correct_answer": "C. Paraneoplastic syndrome due to antibodies formation against presynaptic calcium receptors", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Paraneoplastic syndrome due to antibodies formation against presynaptic calcium receptors</p>\n<p><strong>Highyeild:</strong></p><p>Lambert Eaton Myasthenic syndrome: As the patient is suffering from lung cancer , and the clinical data highly suggest paraneoplastic syndrome due to antibodies formation against presynaptic calcium channels . It is an example of type 2 HSR . Lambert-Eaton myasthenic syndrome is an autoimmune disorder caused by antibodies that block acetylcholine release by inhibiting a presynaptic calcium channel . In contrast to myasthenia gravis, rapid repetitive stimulation increases muscle response . Muscle strength is augmented after a few seconds of muscle activity. Patients typically present with weakness in their extremities . In about half of cases, there is an underlying malignancy , most often neuroendocrine carcinoma of the lung .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Paraneoplastic syndrome due to antibodies formation against muscle spindles. Incorrect . Option: B. Paraneoplastic syndrome due to antibodies formation against postsynaptic acetylcholine receptors. Incorrect . Option: D. Metastasis of lung cancer. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Myasthenia gravis Lambert Eaton syndrome Antibody against AchR antibody Antibody against voltage gated calcium channel Associated with Thymic tumor Associated with Small cell lung cancer Weakness worsen on prolonged exercise Weakness improves on prolonged exercise Normal Deep tendon reflex Decreased or absent deep tendon reflex Autonomic dysfunction is absent Autonomic dysfunction is present On repeated nerve stimulation, there is decremental response On repeated nerve stimulation, there is incremental response</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 20-year lady came to OPD with complaints of sneezing and watery discharge from her nose for 2 days. What is the major lymphocyte present in this condition?", "options": [{"label": "A", "text": "Th1 cells", "correct": false}, {"label": "B", "text": "Th2 cells", "correct": true}, {"label": "C", "text": "Th17 cells", "correct": false}, {"label": "D", "text": "CD8 T cells", "correct": false}], "correct_answer": "B. Th2 cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>2 cells Allergic reactions and parasitic infestations stimulate Th2 cells . Th2 cells produce IL-4 , which stimulates B cells to differentiate into IgE-secreting plasma cells , and IL-5 , which stimulates the production of eosinophils in the marrow and activates eosinophils at sites of immune responses. Eosinophils and mast cells bind to IgE-coated microbes such as helminthic parasites and function to eliminate helminths. Th2 cells also induce the “alternative” pathway of macrophage activation, which is associated with tissue repair and fibrosis . table,tr,th,td {border:1px solid black;} Cytokines produced TH1 TH2 TH17 Cytokines that induce this subset IFN-γ, IL-12 IL-4 TGF- β IL-6, IL-1, IL-23 Immunological reactions triggered Macrophage activation Stimulation of IgE production, activation of mast cells and eosinophils Recruitment of neutrophils, monocytes Host defense against Intracellular microbes Helminthic parasites Extracellular bacteria, fungi Role in disease Immune-mediated chronic inflammatory diseases (often autoimmune) Allergies Immune-mediated chronic inflammatory diseases (often autoimmune) Subsets of helper T (Th) cells. In response to stimuli (mainly cytokines) present at the time of antigen recognition, naïve CD4+ T cells may differentiate into populations of effector cells that produce distinct sets of cytokines and perform different functions. The dominant immune reactions elicited by each subset, and its role in host defense and immunologic diseases, are summarized. These populations may be capable of converting from one to another. Some activated T cells produce multiple cytokines and do not fall into a distinct subset</p>\n<p><strong>Highyeild:</strong></p><p>Immediate , or type I hypersensitivity is a rapid immunologic reaction occurring in a previously sensitized individual that is triggered by the binding of an antigen to IgE antibody on the surface of mast cells. These reactions are often called allergies , and the antigens that elicit them are allergens.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Th1 cells. Chronic antigens and intracellular microbes stimulate Th1 cells . Option: C. Th17 cells. Extracellular microbes, bacteria, and fungi stimulate Th17 cells . Option: D. CD8 T cells. Activated CD8+ T lymphocytes differentiate into CTLs that kill cells harboring microbes in the cytoplasm .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "On stimulation of Th2 cells , it releases-", "options": [{"label": "A", "text": "IL- 4", "correct": false}, {"label": "B", "text": "IL-13", "correct": false}, {"label": "C", "text": "IL- 5", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Th2 cells produce: IL-4 , which stimulates B cells to differentiate into IgE-secreting plasma cells . IL-5 , which stimulates the production of eosinophils in the marrow and activates eosinophils at sites of immune responses. Eosinophils and mast cells bind to IgE-coated microbes such as helminthic parasites and function to eliminate helminths . Th2 cells also induce the “ alternative” pathway of macrophage activation , which is associated with tissue repair and fibrosis . Cytokines produced TH1 TH2 TH17 Cytokines that induce this subset IFN-γ, IL-12 IL-4 TGF- β IL-6, IL-1, IL-23 Immunological reactions triggered Macrophage activation Stimulation of IgE production, activation of mast cells and eosinophils Recruitment of neutrophils, monocytes Host defense against Intracellular microbes Helminthic parasites Extracellular bacteria, fungi Role in disease Immune-mediated chronic inflammatory diseases (often autoimmune) Allergies Immune-mediated chronic inflammatory diseases (often autoimmune) Subsets of helper T (Th) cells. In response to stimuli (mainly cytokines) present at the time of antigen recognition, naïve CD4+ T cells may differentiate into populations of effector cells that produce distinct sets of cytokines and perform different functions. The dominant immune reactions elicited by each subset, and its role in host defense and immunologic diseases, are summarized. These populations may be capable of converting from one to another. Some activated T cells produce multiple cytokines and do not fall into a distinct subset</p>\n<p><strong>Highyeild:</strong></p><p>Immediate , or type I hypersensitivity is a rapid immunologic reaction occurring in a previously sensitized individual that is triggered by the binding of an antigen to IgE antibody on the surface of mast cells. These reactions are often called allergies , and the antigens that elicit them are allergens.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, B and C are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "On exposure to fungal infections, what are the cytokines that induce Th17 cells?", "options": [{"label": "A", "text": "TGF- beta", "correct": false}, {"label": "B", "text": "IL- 1", "correct": false}, {"label": "C", "text": "IL- 6", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Th17 cells , so called because the signature cytokine of these cells is IL-17 , recruit neutrophils and monocytes , which destroy extracellular bacteria and fungi and are involved in some inflammatory diseases.</p>\n<p><strong>Highyeild:</strong></p><p>Naïve CD4+ T cells recognize peptides displayed by Dendritic Cells (DCs) and secrete IL-2 , which functions as an autocrine growth factor to stimulate the proliferation of the antigen-responsive T cells . Subsequent differentiation of antigen-stimulated T cells to Th1 or Th17 cells is driven by the cytokines produced by APCs at the time of T-cell activation. In some situations, the APCs (DCs and macrophages) produce IL-12 , which induces the differentiation of CD4+ T cells to the Th1 subset . IFN-γ produced by these effector cells promotes further Th1 development, thus amplifying the reaction. If the APCs produce the inflammatory cytokines IL-1, IL-6, and a close relative of IL-12 called IL-23 , the T cells are induced to differentiate to the Th17 subset . Activated Th17 cells then secrete IL-17, IL-22, chemokines , and several other cytokines. Collectively, these cytokines recruit neutrophils and monocytes to the reaction , thus promoting inflammation . Th17 cells also produce IL-21 , which amplifies the Th17 response . Cytokines produced IFN-γ IL-4, IL-5, IL-13 IL-17, IL-22 Cytokines that induce this subset IFN-γ, IL-12 IL-4 TGF- β IL-6, IL-1, IL-23 Immunological reactions triggered Macrophage activation Stimulation of IgE production, activation of mast cells and eosinophils Recruitment of neutrophils, monocytes Host defense against Intracellular microbes Helminthic parasites Extracellular bacteria, fungi Role in disease Immune-mediated chronic inflammatory diseases (often autoimmune) Allergies Immune-mediated chronic inflammatory diseases (often autoimmune) Subsets of helper T (Th) cells. In response to stimuli (mainly cytokines) present at the time of antigen recognition, naïve CD4+ T cells may differentiate into populations of effector cells that produce distinct sets of cytokines and perform different functions. The dominant immune reactions elicited by each subset, and its role in host defense and immunologic diseases, are summarized. These populations may be capable of converting from one to another. Some activated T cells produce multiple cytokines and do not fall into a distinct subset</p>\n<p><strong>Random:</strong></p><p>Explanation for all options:- Options A, B and D are correct</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "On prolonged exposure to an intracellular antigen, what are the cytokines released by APCs to induce T helper cells? Which type of T helper cell is stimulated?", "options": [{"label": "A", "text": "IL-12, Th1", "correct": true}, {"label": "B", "text": "IL-4, Th2", "correct": false}, {"label": "C", "text": "IL- 6, Th17", "correct": false}, {"label": "D", "text": "IL- 1, Th1", "correct": false}], "correct_answer": "A. IL-12, Th1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IL-12, Th1 Dendritic cells capture microbial antigens from epithelia and tissues and transport the antigens to lymph nodes . During this process, the dendritic cells mature and express high levels of MHC molecules and costimulators . Naïve T cells recognize MHC-associated peptide antigens displayed on dendritic cells. The T cells are activated to proliferate and differentiate into effector and memory cells , which migrate to sites of infection and serve various functions in cell-mediated immunity. CD4+ effector T cells of the Th1 subset recognize the antigens of microbes ingested by phagocytes and activate the phagocytes to kill the microbes; other subsets of effector cells enhance leukocyte recruitment and stimulate different types of immune responses. table,tr,th,td {border:1px solid black;} Cytokines produced IFN-γ IL-4, IL-5, IL-13 IL-17, IL-22 Cytokines that induce this subset IFN-γ, IL-12 IL-4 TGF- β IL-6, IL-1, IL-23 Immunological reactions triggered Macrophage activation Stimulation of IgE production, activation of mast cells and eosinophils Recruitment of neutrophils, monocytes Host defense against Intracellular microbes Helminthic parasites Extracellular bacteria, fungi Role in disease Immune-mediated chronic inflammatory diseases (often autoimmune) Allergies Immune-mediated chronic inflammatory diseases (often autoimmune) Subsets of helper T (Th) cells. In response to stimuli (mainly cytokines) present at the time of antigen recognition, naïve CD4+ T cells may differentiate into populations of effector cells that produce distinct sets of cytokines and perform different functions. The dominant immune reactions elicited by each subset, and its role in host defense and immunologic diseases, are summarized. These populations may be capable of converting from one to another. Some activated T cells produce multiple cytokines and do not fall into a distinct subset</p>\n<p><strong>Highyeild:</strong></p><p>Cell-mediated hypersensitivity (Type IV Hypersensitivity) is caused mainly by inflammation resulting from cytokines produced by CD4+ T cells . CD4+ T cell-mediated hypersensitivity induced by environmental and self-antigens is the cause of many autoimmune and other chronic inflammatory diseases . On repeat exposure to an antigen, Th1 cells secrete cytokines, mainly IFN-γ , which are responsible for many of the manifestations of delayed-type hypersensitivity . IFN-γ-activated (“classically activated”) macrophages are altered in several ways: their ability to phagocytose and kill microorganisms is markedly augmented; they express more class II MHC molecules on the surface, enhancing antigen presentation ; they secrete TNF, IL-1, and chemokines, which promote inflammation , and they produce more IL-12, amplifying the Th1 response .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. IL-4, Th2. It is induced by allergies and parasitic infections . Option: C. IL- 6, Th17. On exposure to extracellular bacteria and fungi . Option: D. IL- 1, Th1. Th1 is stimulated by IL-12 and IFN-γ .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding CD8 T cells?", "options": [{"label": "A", "text": "Cytotoxic T cells", "correct": false}, {"label": "B", "text": "Act via perforins and granzymes", "correct": false}, {"label": "C", "text": "Kills tumor cells", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Activated CD8+ T lymphocytes differentiate into Cytotoxic T Lymphocytes (CTLs) that kill cells harboring microbes in the cytoplasm . By destroying the infected cells, CTLs eliminate the reservoirs of infection. CTLs also kill tumor cells by recognizing tumor-specific antigens derived from mutated or abnormal cytoplasmic proteins.</p>\n<p><strong>Random:</strong></p><p>Explanation for rest options: - Option: A. Cytotoxic T cells. Correct . Option: B. Act via perforins and granzymes. Correct . Option: D. Kills tumor cells. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The principal mechanism of T cell-mediated killing of targets involves perforins and granzymes , preformed mediators contained in the lysosome-like granules of CTLs. CTLs that recognize the target cells secrete a complex consisting of perforin, granzymes, and other proteins that enters target cells by endocytosis . In the target cell cytoplasm, perforin facilitates the release of the granzymes from the complex. Granzymes are proteases that cleave and activate caspases, which induce apoptosis of the target cells</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The Th1 type of cells is most dependent on:", "options": [{"label": "A", "text": "INF-gamma", "correct": true}, {"label": "B", "text": "IL-4", "correct": false}, {"label": "C", "text": "IL-5", "correct": false}, {"label": "D", "text": "IL-6", "correct": false}], "correct_answer": "A. INF-gamma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>INF-gamma</p>\n<p><strong>Highyeild:</strong></p><p>Cell-mediated hypersensitivity (Type IV Hypersensitivity) is caused mainly by inflammation resulting from cytokines produced by CD4+ T cells . CD4+ T cell-mediated hypersensitivity induced by environmental and self-antigens is the cause of many autoimmune and other chronic inflammatory diseases . On repeat exposure to an antigen, Th1 cells secrete cytokines, mainly IFN-γ , which are responsible for many of the manifestations of delayed-type hypersensitivity . IFN-γ-activated (“classically activated”) macrophages are altered in several ways: their ability to phagocytose and kill microorganisms is markedly augmented; they express more class II MHC molecules on the surface, enhancing antigen presentation ; they secrete TNF, IL-1, and chemokines, which promote inflammation , and they produce more IL-12, amplifying the Th1 response .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. IL-4. Involved in Type I Hypersensitivity reaction (early phase) . Option: C. IL-5. Involved in Type I Hypersensitivity reaction (late phase) . Option: D. IL-6. Endogenous pyrogen is involved in inflammation .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Th17 cells are involved in:-", "options": [{"label": "A", "text": "Macrophage activation", "correct": false}, {"label": "B", "text": "Killing intracellular microbes", "correct": false}, {"label": "C", "text": "Severe neutrophilic inflammation", "correct": true}, {"label": "D", "text": "Important in helminthic infection", "correct": false}], "correct_answer": "C. Severe neutrophilic inflammation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Severe neutrophilic inflammation</p>\n<p><strong>Highyeild:</strong></p><p>Naïve CD4+ T cells recognize peptides displayed by Dendritic Cells (DCs) and secrete IL-2 , which functions as an autocrine growth factor to stimulate the proliferation of the antigen-responsive T cells . Subsequent differentiation of antigen-stimulated T cells to Th1 or Th17 cells is driven by the cytokines produced by APCs at the time of T-cell activation. In some situations, the APCs (DCs and macrophages) produce IL-12 , which induces the differentiation of CD4+ T cells to the Th1 subset . IFN-γ produced by these effector cells promotes further Th1 development, thus amplifying the reaction. If the APCs produce the inflammatory cytokines IL-1, IL-6, and a close relative of IL-12 called IL-23 , the T cells are induced to differentiate to the Th17 subset . Activated Th17 cells then secrete IL-17, IL-22, chemokines , and several other cytokines. Collectively, these cytokines recruit neutrophils and monocytes to the reaction , thus promoting inflammation . Th17 cells also produce IL-21 , which amplifies the Th17 response .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Macrophage activation. Seen with Th1 cells . Option: B. Killing intracellular microbes. Seen with Th1 cells . Option: D. Important in helminthic infection. Seen with Th2 cells .</p>\n<p><strong>Extraedge:</strong></p><p>table,tr,th,td {border:1px solid black;} Cytokines produced IFN-γ IL-4, IL-5, IL-13 IL-17, IL-22 Cytokines that induce this subset IFN-γ, IL-12 IL-4 TGF- β IL-6, IL-1, IL-23 Immunological reactions triggered Macrophage activation Stimulation of IgE production, activation of mast cells and eosinophils Recruitment of neutrophils, monocytes Host defense against Intracellular microbes Helminthic parasites Extracellular bacteria, fungi Role in disease Immune-mediated chronic inflammatory diseases (often autoimmune) Allergies Immune-mediated chronic inflammatory diseases (often autoimmune) Subsets of helper T (Th) cells. In response to stimuli (mainly cytokines) present at the time of antigen recognition, naïve CD4+ T cells may differentiate into populations of effector cells that produce distinct sets of cytokines and perform different functions. The dominant immune reactions elicited by each subset, and its role in host defense and immunologic diseases, are summarized. These populations may be capable of converting from one to another. Some activated T cells produce multiple cytokines and do not fall into a distinct subset</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 30-year-old female has paraesthesia, pins, and needle sensation, U/L decreased visual acuity, and brisk tendon reflexes, it was found that she has internuclear ophthalmoplegia. MRI brain was done and there was a Dawson fingers appearance. What is your diagnosis and what type of hypersensitivity reaction is responsible for this disease?", "options": [{"label": "A", "text": "Multiple Sclerosis, HSR type 1", "correct": false}, {"label": "B", "text": "Myasthenia Gravis, HSR type 2", "correct": false}, {"label": "C", "text": "Myasthenia Gravis, HSR type 3", "correct": false}, {"label": "D", "text": "Multiple Sclerosis, HSR type 4", "correct": true}], "correct_answer": "D. Multiple Sclerosis, HSR type 4", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple Sclerosis, HSR type 4</p>\n<p><strong>Highyeild:</strong></p><p>From the given clinical and radiological analysis diagnosis of Multiple Sclerosis is made. Dawson's fingers' appearance on MRI is characteristic of multiple sclerosis . Multiple sclerosis (MS) is an autoimmune demyelinating disorder characterized by distinct episodes of neurologic deficits , separated in time , attributable to white matter lesions that are separated in space . The lesions of MS are caused by an autoimmune response directed against components of the myelin sheath . It is a type 4 hypersensitivity reaction . How the autoimmune reaction is initiated is not understood; the role of viral infection (e.g., EBV ) has been proposed but remains controversial. MS lesions can occur anywhere in the CNS and consequently may induce a wide range of clinical manifestations , certain patterns of neurologic symptoms and signs are more common. Unilateral visual impairment due to involvement of the optic nerve ( optic neuritis, retrobulbar neuritis ) is a frequent initial manifestation of MS . McDonald’s criteria are used for the diagnosis of MS .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Multiple Sclerosis, HSR type 1. MS is Type 4 HSR. Option: B. Myasthenia Gravis, HSR type 2. Myasthenia is not the diagnosis as Myasthenia presents with progressive muscle weakness throughout the day with weakness of extraocular muscles causing ptosis . Option: C. Myasthenia Gravis, HSR type 3. Myasthenia is Type 2 HSR .</p>\n<p><strong>Extraedge:</strong></p><p>Treatment for MS: Steroids Vitamin D Oral drugs like Fingolimod Injectables like IFN beta, Natalizumab Serious side effect of Natalizumab includes Progressive Multifocal Leukoencephalopathy due to infection with JC virus, thus patients should be JCV naive (JCV negative) before starting treatment with Natalizumab .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 20-year-old man has a fever, chest pain, night sweat, and blood in his sputum. A Mantoux test was performed and shows 7 mm of induration. What is true?", "options": [{"label": "A", "text": "Result is diagnostic of TB", "correct": false}, {"label": "B", "text": "It is a type 4 hypersensitivity reaction", "correct": true}, {"label": "C", "text": "It is a normal result. He is not exposed to TB", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. It is a type 4 hypersensitivity reaction", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1689839840090-QTDP047009IMG1.JPG", "https://dbmi-data.s3.ap-south-1.amazonaws.com/QTDP045010IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is a type 4 hypersensitivity reaction Positive Mantoux test is type 4 HSR . Mantoux Test interpretation:</p>\n<p><strong>Highyeild:</strong></p><p>Cell-mediated hypersensitivity (Type IV Hypersensitivity) is caused mainly by inflammation resulting from cytokines produced by CD4+ T cells . CD4+ T cell-mediated hypersensitivity induced by environmental and self-antigens is the cause of many autoimmune and other chronic inflammatory diseases . On repeat exposure to an antigen, Th1 cells secrete cytokines, mainly IFN-γ , which are responsible for many of the manifestations of delayed-type hypersensitivity . IFN-γ-activated (“classically activated”) macrophages are altered in several ways: their ability to phagocytose and kill microorganisms is markedly augmented; they express more class II MHC molecules on the surface, enhancing antigen presentation ; they secrete TNF, IL-1, and chemokines, which promote inflammation , and they produce more IL-12, amplifying the Th1 response .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. The result is a diagnostic of TB. The Mantoux test is just a screening test, not a diagnostic test . Option: C. It is a normal result. He is not exposed to TB. False, < 5 mm is normal . Option: D. All are true. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 26-year-old female has fatigue, fever, loss of appetite and weight, abdominal pain, shortness of breath, and she has high blood pressure. She has firm, tender subcutaneous nodules. She is also positive for HBcAg. After investigations diagnosis of polyarteritis nodosa was made. What is true?", "options": [{"label": "A", "text": "She is suffering from Takayasu arteritis", "correct": false}, {"label": "B", "text": "It is due to immune complex-mediated type 3 HSR", "correct": true}, {"label": "C", "text": "It is due to type 1 HSR", "correct": false}, {"label": "D", "text": "Both A and B", "correct": false}], "correct_answer": "B. It is due to immune complex-mediated type 3 HSR", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is due to immune complex-mediated type 3 HSR</p>\n<p><strong>Highyeild:</strong></p><p>Polyarteritis Nodosa (PAN) Classic polyarteritis nodosa (PAN) is a systemic vasculitis characterized by necrotizing inflammatory lesions that affect medium-sized and small muscular arteries , preferentially at vessel bifurcations, typically affects renal and visceral vessels but SPARES the pulmonary circulation . MNEMONIC: In PAN P ulmonary A rtery is N ot Involved It is frequently accompanied by fibrinoid necrosis and luminal thrombosis . Hepatitis B virus (HBV) infection is strongly linked with PAN . Evidence for immune complex–the induced disease is confined to HBV-related PAN that is Type 3 HSR .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: C. It is due to type 1 HSR. False, PAN is due to Type 3 HSR . Option: D. Both A and B. Incorrect option .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An 8-year-old boy is brought by his parents with complaints of joint pain, abdominal pain, and skin rashes as given in the image. What is true?", "options": [{"label": "A", "text": "These purpura are due to thrombocytopenia", "correct": false}, {"label": "B", "text": "It is an immune complex-mediated type 3 vasculitis", "correct": true}, {"label": "C", "text": "Diagnosis is of Kawasaki vasculitis", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. It is an immune complex-mediated type 3 vasculitis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1689839888829-QTDP047011IMG1.JPG", "https://dbmi-data.s3.ap-south-1.amazonaws.com/QTDP045012IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is an immune complex-mediated type 3 vasculitis</p>\n<p><strong>Highyeild:</strong></p><p>Henoch-Schonlein purpura (HSP): From the given data and image diagnosis of Henoch-Schonlein purpura is most likely. Henoch-Schonlein purpura (HSP) (also known as IgA vasculitis ) is a disorder that causes the inflammation of small blood vessels in the skin, joints, intestines, and kidneys . The most characteristic feature of this form of vasculitis is a purplish rash, typically on the lower legs and buttocks . Henoch-Schonlein purpura can also cause abdominal pain and arthralgia . Renal manifestations occur in one-third of patients and include gross or microscopic hematuria, nephritic syndrome, nephrotic syndrome, or some combination of these . A small number of patients, mostly adults, develop a rapidly progressive form of glomerulonephritis with many crescents (RPGN) . Thrombocytosis is seen (increase in platelet count). Treatment: Steroids</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. These purpura are due to thrombocytopenia. False, HSP doesn’t show thrombocytopenia . Option: C. Diagnosis is Kawasaki vasculitis. False, the diagnosis is HSP . Option: D. All are true. False .</p>\n<p><strong>Extraedge:</strong></p><p>Kawasaki vasculitis: Kawasaki disease is a disease of unknown etiology that most frequently affects infants and children under 5 years of age . Inflammation occurs in medium-sized muscular arteries throughout the body including the coronary artery . It typically presents with conjunctival and oral erythema and blistering, edema of the hands and feet, erythema of the palms and soles, a desquamative rash, and cervical lymph node enlargement (hence its other name, mucocutaneous lymph node syndrome ). Treatment: i/v Ig and Aspirin. NEVER Steroids .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 19 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding the pathogenesis of dilated cardiomyopathy except:", "options": [{"label": "A", "text": "In genetic causes, a mutation in the TTN gene is common", "correct": false}, {"label": "B", "text": "Myocarditis can progress to dilated cardiomyopathy", "correct": false}, {"label": "C", "text": "Alcohol abuse can also cause dilated cardiomyopathy", "correct": false}, {"label": "D", "text": "Storage disorders can also cause dilated cardiomyopathy", "correct": true}], "correct_answer": "D. Storage disorders can also cause dilated cardiomyopathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Storage disorders can also cause dilated cardiomyopathy False, Storage disorders result in Hypertrophic cardiomyopathy .</p>\n<p><strong>Highyeild:</strong></p><p>Cardiomyopathies: Cardiomyopathies are a heterogeneous group of diseases of the myocardium associated with mechanical and/or electrical dysfunction that usually (but not invariably) exhibit inappropriate ventricular hypertrophy or dilatatio n and are due to a variety of causes that frequently are genetic . Cardiomyopathies either are confined to the heart or are part of generalized systemic disorders , often leading to cardiovascular death or progressive heart failure-related disability . Cardiomyopathies are anatomically divided into 3 categories: Dilated cardiomyopathy (DCM) (including arrhythmogenic cardiomyopathy): Systolic dysfunction (impairment of contractility ) Hypertrophic cardiomyopathy : Diastolic dysfunction (impairment of filling ) Restrictive cardiomyopathy : Diastolic dysfunction (impairment of filling ) DCM is the most common (90% of cases), and restrictive cardiomyopathy is the least frequent . Dilated Cardiomyopathy DCM is characterized morphologically and functionally by progressive cardiac dilation and contractile (systolic) dysfunction, usually with concomitant hypertrophy. Truncation mutations in TTN , a gene that encodes titin (so-called because it is the largest protein expressed in humans), may account for approximately 10% to 20% of all cases of DCM Causes of Dilated Cardiomyopathy: Genetic ( mutations in TTN ) Alcohol Peripartum Myocarditis Hemochromatosis Chronic anemia Anthracycline medications Sarcoidosis Idiopathic</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. In genetic causes, a mutation in the TTN gene is common. Correct . Option: B. Myocarditis can progress to dilated cardiomyopathy. Correct . Option: C. Alcohol abuse can also cause dilated cardiomyopathy. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Supraphysiologic stress can also result in DCM. This can happen with persistent tachycardia, hyperthyroidism, or even during development, as in the fetuses of insulin-dependent diabetic mothers . This can happen in individuals with pheochromocytomas , and tumors that elaborate epinephrine ; the use of cocaine or vasopressor agents such as dopamine can have similar consequences. Such “ catecholamine effect ” also occurs in the setting of intense autonomic stimulation , for example, secondary to intracranial lesions or emotional duress . Takotsubo cardiomyopathy is an entity characterized by left ventricular contractile dysfunction after extreme psychological stress (thus also called broken heart syndrome ); the affected myocardium may be stunned or show contraction band necrosis . For unclear reasons, the left ventricular apex is most often affected, leading to “ apical ballooning ” that resembles a takotsubo, Japanese for “ fishing pot for trapping octopus ” (hence, the name).</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Naxos syndrome is associated with which cardiomyopathy?", "options": [{"label": "A", "text": "Dilated cardiomyopathy", "correct": false}, {"label": "B", "text": "Restrictive cardiomyopathy", "correct": false}, {"label": "C", "text": "Hypertrophic cardiomyopathy", "correct": false}, {"label": "D", "text": "Arrhythmogenic right Ventricular Cardiomyopathy", "correct": true}], "correct_answer": "D. Arrhythmogenic right Ventricular Cardiomyopathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Arrhythmogenic right Ventricular Cardiomyopathy Naxos syndrome is a disorder characterized by arrhythmogenic right ventricular cardiomyopath y and hyperkeratosis of plantar palmar skin surfaces specifically associated with mutations in the gene encoding the desmosome-associated protein plakoglobin .</p>\n<p><strong>Highyeild:</strong></p><p>Arrhythmogenic right ventricular cardiomyopathy is an autosomal dominant disorder that classically manifests with right-sided heart failure and rhythm disturbances , which can cause sudden cardiac death . Left-sided involvement with left-sided heart failure can also occur . Classically, the right ventricular wall is severely attenuated due to the loss of myocytes , accompanied by massive fatty infiltration and focal fibrosis . Although mononuclear inflammation may be present around degenerating cardiomyocytes, arrhythmogenic cardiomyopathy is NOT considered inflammatory cardiomyopathy . Classical arrhythmogenic cardiomyopathy has an autosomal dominant inheritance with variable penetrance; many of the causal mutations involve genes encoding desmosomal junctional proteins at the intercalated disk (e.g., plakoglobin) as well as proteins that interact with the desmosome (e.g., the intermediate filament desmin). Naxos syndrome is a disorder characterized by arrhythmogenic cardiomyopathy and hyperkeratosis of plantar and palmar ski n surfaces and is also associated with plakoglobin mutations .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Dilated cardiomyopathy. Incorrect . Option: B. Restrictive cardiomyopathy. Incorrect . Option: C. Hypertrophic cardiomyopathy. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mutation of which gene is most commonly associated with hypertrophic cardiomyopathy:", "options": [{"label": "A", "text": "β-myosin heavy chain (β-MHC)", "correct": true}, {"label": "B", "text": "Cardiac TnT", "correct": false}, {"label": "C", "text": "α-tropomyosin", "correct": false}, {"label": "D", "text": "Cardiac TnI", "correct": false}], "correct_answer": "A. β-myosin heavy chain (β-MHC)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>β-myosin heavy chain (β-MHC)</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophic Cardiomyopathy (HCM): Hypertrophic cardiomyopathy is a common, clinically heterogeneous, genetic disorder characterized by myocardial hypertrophy , poorly compliant left ventricular myocardium leading to abnormal diastolic filling , and (in about one-third of cases) intermittent ventricular outflow obstruction It is the leading cause of left ventricular hypertrophy unexplained by other clinical or pathologic causes . The heart is thick-walled, heavy, and hyper-contracting. HCM causes primarily diastolic dysfunction ; systolic function is usually preserved. The pattern of transmission is autosomal dominant with variable penetrance . HCM is most commonly caused by mutation s in any one of several genes that encode sarcomeric proteins Mutations causing HCM are found most commonly in the genes encoding myosin-binding protein C (MYBP-C) or β-myosin heavy chain (β-MHC/MYH7) , followed by the genes coding for cardiac TnI , TnT , and α-tropomyosin ; overall, these account for 70% to 80% of all cases. The essential feature of HCM is massive myocardial hypertrophy , usually WITHOUT ventricular dilation The classic pattern involves disproportionate thickening of the ventricular septum relative to the left ventricle free wall, termed asymmetric septal hypertrophy . In about 10% of cases, the hypertrophy is concentric and symmetrical . On longitudinal sectioning, the normally round-to-ovoid left ventricular cavity may be compressed into a “banana-like” configuration by bulging the ventricular septum into the lumen. Although marked hypertrophy can involve the entire septum, it is usually most prominent in the subaortic region ; the left ventricular outflow tract often exhibits a fibrous endocardial plaque and thickening of the anterior mitral leaflet . Both findings result from contact of the anterior mitral leaflet with the septum during ventricular systole; they correlate with the echocardiographic “ systolic anterior motion ” of the anterior leaflet, with functional left ventricular outflow tract obstruction during systole.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B: Cardiac TnT. Incorrect . Option: C: α-tropomyosin. Incorrect . Option: D. Cardiac TnI. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>The most important histologic features of HCM myocardium are: Massive myocyte hypertrophy Haphazard disarray of bundles of myocytes, individual myocytes, and contractile elements in sarcomeres within cells (termed myofiber disarray ) Fibrotic narrowing of small intramural arteries Interstitial and replacement fibrosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding histological features of hypertrophic cardiomyopathy except:", "options": [{"label": "A", "text": "Asymmetric septal hypertrophy", "correct": false}, {"label": "B", "text": "Massive myocardial hypertrophy", "correct": false}, {"label": "C", "text": "Organised bundle of myocytes in sarcomeres", "correct": true}, {"label": "D", "text": "Interstitial and replacement fibrosis", "correct": false}], "correct_answer": "C. Organised bundle of myocytes in sarcomeres", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Organised bundle of myocytes in sarcomeres False , Haphazard disarray of bundles of myocytes ie disorganized , individual myocytes, and contractile elements in sarcomeres within cells (termed myofiber disarray )</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophic Cardiomyopathy (HCM): Hypertrophic cardiomyopathy is a common, clinically heterogeneous, genetic disorder characterized by myocardial hypertrophy , poorly compliant left ventricular myocardium leading to abnormal diastolic filling , and (in about one-third of cases) intermittent ventricular outflow obstruction It is the leading cause of left ventricular hypertrophy unexplained by other clinical or pathologic causes . The heart is thick-walled, heavy, and hyper-contracting. HCM causes primarily diastolic dysfunction ; systolic function is usually preserved. The pattern of transmission is autosomal dominant with variable penetrance . HCM is most commonly caused by mutation s in any one of several genes that encode sarcomeric proteins Mutations causing HCM are found most commonly in the genes encoding myosin-binding protein C (MYBP-C) or β-myosin heavy chain (β-MHC/MYH7) , followed by the genes coding for cardiac TnI , TnT , and α-tropomyosin ; overall, these account for 70% to 80% of all cases. The essential feature of HCM is massive myocardial hypertrophy , usually WITHOUT ventricular dilation The classic pattern involves disproportionate thickening of the ventricular septum relative to the left ventricle free wall, termed asymmetric septal hypertrophy . In about 10% of cases, the hypertrophy is concentric and symmetrical . On longitudinal sectioning, the normally round-to-ovoid left ventricular cavity may be compressed into a “banana-like” configuration by bulging the ventricular septum into the lumen. Although marked hypertrophy can involve the entire septum, it is usually most prominent in the subaortic region ; the left ventricular outflow tract often exhibits a fibrous endocardial plaque and thickening of the anterior mitral leaflet . Both findings result from contact of the anterior mitral leaflet with the septum during ventricular systole; they correlate with the echocardiographic “ systolic anterior motion ” of the anterior leaflet, with functional left ventricular outflow tract obstruction during systole.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Asymmetric septal hypertrophy. Correct . Option: B. Massive myocardial hypertrophy. Correct . Option: D. Interstitial and replacement fibrosis. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The most important histologic features of HCM myocardium are: Massive myocyte hypertrophy Haphazard disarray of bundles of myocytes, individual myocytes, and contractile elements in sarcomeres within cells (termed myofiber disarray ) Fibrotic narrowing of small intramural arteries Interstitial and replacement fibrosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old patient died of heart failure and after the autopsy, a histopathological feature of the cardiac wall is shown in the diagram to identify the type of cardiomyopathy:", "options": [{"label": "A", "text": "Dilated cardiomyopathy", "correct": false}, {"label": "B", "text": "Restrictive cardiomyopathy", "correct": false}, {"label": "C", "text": "Hypertrophic cardiomyopathy", "correct": true}, {"label": "D", "text": "Arrhythmogenic right ventricular cardiomyopathy", "correct": false}], "correct_answer": "C. Hypertrophic cardiomyopathy", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831286742-QTDP098006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hypertrophic cardiomyopathy The given figure shows massive myocyte hypertrophy, with enlarged transverse myocyte diameters, haphazard disarray of bundles of myocytes, and interstitial and replacement fibrosis suggestive of Hypertrophic cardiomyopathy</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophic Cardiomyopathy (HCM): Hypertrophic cardiomyopathy is a common, clinically heterogeneous, genetic disorder characterized by myocardial hypertrophy , poorly compliant left ventricular myocardium leading to abnormal diastolic filling , and (in about one-third of cases) intermittent ventricular outflow obstruction It is the leading cause of left ventricular hypertrophy unexplained by other clinical or pathologic causes . The heart is thick-walled, heavy, and hyper-contracting. HCM causes primarily diastolic dysfunction ; systolic function is usually preserved. The pattern of transmission is autosomal dominant with variable penetrance . HCM is most commonly caused by mutation s in any one of several genes that encode sarcomeric proteins Mutations causing HCM are found most commonly in the genes encoding myosin-binding protein C (MYBP-C) or β-myosin heavy chain (β-MHC/MYH7) , followed by the genes coding for cardiac TnI , TnT , and α-tropomyosin ; overall, these account for 70% to 80% of all cases. The essential feature of HCM is massive myocardial hypertrophy , usually WITHOUT ventricular dilation The classic pattern involves disproportionate thickening of the ventricular septum relative to the left ventricle free wall, termed asymmetric septal hypertrophy . In about 10% of cases, the hypertrophy is concentric and symmetrical . On longitudinal sectioning, the normally round-to-ovoid left ventricular cavity may be compressed into a “banana-like” configuration by bulging the ventricular septum into the lumen. Although marked hypertrophy can involve the entire septum, it is usually most prominent in the subaortic region ; the left ventricular outflow tract often exhibits a fibrous endocardial plaque and thickening of the anterior mitral leaflet . Both findings result from contact of the anterior mitral leaflet with the septum during ventricular systole; they correlate with the echocardiographic “ systolic anterior motion ” of the anterior leaflet, with functional left ventricular outflow tract obstruction during systole.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Dilated cardiomyopathy. Incorrect . Option: B. Restrictive cardiomyopathy. Incorrect . Option: D. Arrhythmogenic right ventricular cardiomyopathy. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>The most important histologic features of HCM myocardium are: Massive myocyte hypertrophy Haphazard disarray of bundles of myocytes, individual myocytes, and contractile elements in sarcomeres within cells (termed myofiber disarray ) Fibrotic narrowing of small intramural arteries Interstitial and replacement fibrosis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Takotsubo Cardiomyopathy associated with emotional stress is a type of-", "options": [{"label": "A", "text": "Hypertrophic cardiomyopathy", "correct": false}, {"label": "B", "text": "Dilated cardiomyopathy", "correct": true}, {"label": "C", "text": "Restrictive cardiomyopathy", "correct": false}, {"label": "D", "text": "Mixed cardiomyopathy", "correct": false}], "correct_answer": "B. Dilated cardiomyopathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dilated cardiomyopathy</p>\n<p><strong>Highyeild:</strong></p><p>Takotsubo cardiomyopathy: Supraphysiologic stress can also result in DCM. This can happen with persistent tachycardia, hyperthyroidism, or even during development, as in the fetuses of insulin-dependent diabetic mothers . This can happen in individuals with pheochromocytomas , and tumors that elaborate epinephrine ; the use of cocaine or vasopressor agents such as dopamine can have similar consequences. Such “ catecholamine effect ” also occurs in the setting of intense autonomic stimulation , for example, secondary to intracranial lesions or emotional duress . Takotsubo cardiomyopathy is an entity characterized by left ventricular contractile dysfunction after extreme psychological stress (thus also called broken heart syndrome ); the affected myocardium may be stunned or show contraction band necrosis . For unclear reasons, the left ventricular apex is most often affected, leading to “ apical ballooning ” that resembles a takotsubo, Japanese for “ fishing pot for trapping octopus ” (hence, the name).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hypertrophic cardiomyopathy. Incorrect . Option: C. Restrictive cardiomyopathy. Incorrect . Option: D. Mixed cardiomyopathy. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Both hyperplasia and hypertrophy are seen in?", "options": [{"label": "A", "text": "Breast enlargement during pregnancy", "correct": true}, {"label": "B", "text": "Uterus during pregnancy", "correct": false}, {"label": "C", "text": "Skeletal muscle enlargement during exercise", "correct": false}, {"label": "D", "text": "Left ventricular hypertrophy during heart failure", "correct": false}], "correct_answer": "A. Breast enlargement during pregnancy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Breast enlargement during pregnancy Hormonal hyperplasia is well illustrated by the proliferation of the glandular epithelium of the female breast at puberty and during pregnancy, usually accompanied by enlargement (hypertrophy) of the glandular epithelial cells.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an increase in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Thus, both hyperplasia and hypertrophy are seen in: Breast during puberty and pregnancy Uterus during pregnancy NOTE: But, here Breast is a better answer as Gravid/Pregnant Uterus demonstrates Hypertrophy > Hyperplasia.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Uterus during pregnancy , is an example of both hypertrophy and hyperplasia but Hypertrophy > Hyperplasia Option: C. Skeletal muscle enlargement during exercise , is an example of Hypertrophy alone. Option: D. Left ventricular hypertrophy during heart failure, as the name suggests is an example of Hypertrophy alone.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old female underwent a preventive health check-up PAP smear. Following an abnormal PAP report, a colposcopy was done and a cervical biopsy was performed. The finding as shown below. Which one is not true about the finding?", "options": [{"label": "A", "text": "Shows squamous metaplasia", "correct": false}, {"label": "B", "text": "Can initiate malignant transformation in the metaplastic epithelium", "correct": false}, {"label": "C", "text": "Result of reprogramming of stem cells that are known to exist in normal tissues", "correct": false}, {"label": "D", "text": "Usually results from an increase in pH", "correct": true}], "correct_answer": "D. Usually results from an increase in pH", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811883313-QTDP003002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Usually results from an increase in pH PAP smear is a screening test used to screen for cervical cancer and can also detect low-stage cervical intraepithelial neoplasia (CIN) . High-risk HPVs (16 and 18) are by far the most important factor in the development of cervical cancer. HPVs are DNA Sites in the female genital tract that are susceptible to infection include areas of squamous epithelial trauma and repair, where the virus may access basal cells, and the immature metaplastic squamous cells that are present at the squamocolumnar junction of the cervix Here, the viruses make factors that interfere with host proteins that regulate cell proliferation. The ability of HPV to act as a carcinogen depends on the viral E6 and E7 proteins , which interfere with the activity of the key tumour suppressor proteins , p53 and RB, respectively . MNEMONIC: E 6 goes with p 5 3 (5 and 6 go together).</p>\n<p><strong>Highyeild:</strong></p><p>Papanicolaou stain includes the following stain : Hemotoxylin : basic dye, stains nuclei Orange G (OG-6) : Acidic counterstain, stains matured and keratinised cells Eosin Azure (Eosin A aka EA) : Second counterstain, which is a mixture of Eosin Y, Light Green SF, and Bismarck Brown Y stain Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation When the tumour invades the basement membrane it is said to be invasive . Dysplasia can be considered as a precursor to malignancy but it does not always progress to cancer.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Shows squamous metaplasia. True . Option: B. Can initiate malignant transformation in the metaplastic epithelium. True . Option: C. Result of reprogramming of stem cells that are known to exist in normal tissues. Definition of metaplasia Option: D. Usually results from an increase in pH. False , it is due to a decrease in pH (acidic pH) .</p>\n<p><strong>Extraedge:</strong></p><p>HPVs are also implicated in squamous cell carcinomas arising at many other sites: Vagina Vulva Penis Anus Tonsil Other oropharyngeal locations. Low oncogenic risk HPVs (6 and 11) are the cause of sexually transmitted vulvar, perineal, and perianal warts (condyloma acuminatum) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding the cellular adaptation shown in the following Image?", "options": [{"label": "A", "text": "It involves an increase in the number of cells", "correct": false}, {"label": "B", "text": "It occurs due to the increased production of cellular proteins", "correct": true}, {"label": "C", "text": "It is a precursor to cancer", "correct": false}, {"label": "D", "text": "It involves the reprogramming of stem cells", "correct": false}], "correct_answer": "B. It occurs due to the increased production of cellular proteins", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811883533-QTDP003003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It occurs due to the increased production of cellular proteins The figure clearly shows an enlarged myocardium. Myocardium is made up of cardiac muscle cells and since these are not capable of dividing , they respond to stress by increasing their cell size . This kind of adaptation is known as HYPERTROPHY . The mechanism of hypertrophy is believed to be due to increased synthesis of cellular proteins . Hence, the correct option is B .</p>\n<p><strong>Highyeild:</strong></p><p>Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation. The features of dysplasia include Pleomorphism Hyperchromatic nuclei High nuclear-to-cytoplasmic ratio Increased mitotic figures Dysplastic changes when they involve the entire thickness of the epithelium without breaching the basement membrane, it is considered preinvasive and is termed carcinoma-in-situ . When the tumor invades the basement membrane it is said to be invasive . Dysplasia can be considered as a precursor to malignancy but it does not always progress to cancer. Dysplasia usually occurs in the metaplastic epithelium but all metaplastic epithelium is not dysplastic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It involves an increase in the number of cells. Incorrect because the increase in the number of cells is referred to as HYPERPLASIA . And myocytes are unable to undergo hyperplasia because they are permanent cells . Option: C. It is a precursor to cancer. Incorrect because hypertrophy is not a pre-malignant condition and hence, there is no increased risk of cancer. D ysplasia is pre-malignant . Option: D. It involves reprogramming of stem cells Incorrect because reprogramming of stem cells is seen in metaplasia .</p>\n<p><strong>Extraedge:</strong></p><p>The cellular adaptation shown here is myocardial hypertrophy (lower left), caused by increased blood pressure requiring greater mechanical effort by myocardial cells. This adaptation leads to the thickening of the left ventricular wall (compare with the normal heart). In reversibly injured myocardium (illustrated schematically, right), there are functional alterations, usually without any gross or microscopic changes but sometimes with cytoplasmic changes such as cellular swelling and fat accumulation . In the specimen showing necrosis , a form of cell death (lower right), the light area in the posterolateral left ventricle represents an acute myocardial infarction caused by reduced blood flow (ischemia).</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25-year-old pregnant woman comes to the office for a routine visit. She has conceived for the first time and hence, she is very much interested in knowing about the physiologic changes that happen during pregnancy. She asks the doctor how the size of the uterus increases in pregnancy by itself. The doctor explains that this is just a physiologic mechanism of hypertrophy and hyperplasia which occurs as a result of increased signalling of a particular hormone. Which hormone is the doctor referring to here?", "options": [{"label": "A", "text": "Estrogen", "correct": true}, {"label": "B", "text": "Prolactin", "correct": false}, {"label": "C", "text": "Testosterone", "correct": false}, {"label": "D", "text": "Progesterone", "correct": false}], "correct_answer": "A. Estrogen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Estrogen During pregnancy , there is hypertrophy and hyperplasia of smooth muscle fibres of the myometrium layer of the uterus to accommodate the fetus. This occurs as a result of estrogen-induced signalling through estrogen receptors that eventually result in increased synthesis of smooth muscle proteins and an increased cell size respectively . Hence, the correct option is A . Physiologic hypertrophy of the uterus during pregnancy. (A) Gross appearance of a normal uterus (right) and a gravid uterus (removed for postpartum bleeding) (left). (B) Small spindle-shaped uterine smooth muscle cells from a normal uterus, compared with (C) large plump cells from the gravid uterus, at the same magnification.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Hyperplasia refers to an increase in cell number Metaplasia refers to a Change in the phenotype of a cell Atrophy refers to the Reduction in the size of an organ or tissue Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Prolactin,is incorrect because prolactin is primarily responsible for the secretion of milk from mammary gland Option: C. Testosterone, is incorrect because testosterone is a male hormone and it hardly plays any role in females. In males , it is implicated in Benign Prostatic Hyperplasia . Option: D. Progesterone,is incorrect because progesterone helps in preparing the uterus for pregnancy and helping in implantation but it does not play any role in causing hypertrophy of the uterus.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In hypertrophy of cardiac muscle, which of the following does not occur?", "options": [{"label": "A", "text": "Induction of fetal genes", "correct": false}, {"label": "B", "text": "Increased secretion of ANP", "correct": false}, {"label": "C", "text": "Increased synthesis of contractile proteins", "correct": false}, {"label": "D", "text": "Decreased production of growth factors", "correct": true}], "correct_answer": "D. Decreased production of growth factors", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Decreased production of growth factors Cardiac muscle hypertrophy refers to an increase in the size of cardiac muscl e cells in response to some kind of stress . In this, there is increased production of growth factors such as IGF 1 which further stimulates the myocardial cell. Thus, this statement is incorrect . Hence, the correct answer is option D.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an increase in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Thus, both hyperplasia and hypertrophy are seen in: Breast during puberty and pregnancy Uterus during pregnancy</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Induction of fetal genes , is a correct statement because, in myocardial hypertrophy, there is induction of fetal isoforms ie switch in gene expression from genes that encode adult-type contractile proteins to genes that encode functionally distinct fetal isoforms of the same proteins. Option: B. Increased secretion of ANP. Correct Option: C. Increased synthesis of contractile proteins. Correct</p>\n<p><strong>Extraedge:</strong></p><p>Hypertrophy refers to an in crease in cell size In Cardiac hypertrophy, the following are seen: Induction of fetal genes α isoform of the myosin heavy chain is replaced by β chain which leads to an increase in the efficiency of myocardial cells . Increased atrial natriuretic factor (ANP) gene expression ANP is a peptide hormone that causes salt secretion by the kidney, decreases blood volume and pressure and therefore serves to reduce hemodynamic load . Increased synthesis of contractile proteins There is an increased synthesis of contractile proteins which helps to increase the overall mechanical performance of the heart .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not an example of physiologic hyperplasia?", "options": [{"label": "A", "text": "Uterus enlargement during pregnancy", "correct": false}, {"label": "B", "text": "Liver regeneration following the donation of the lobe of the liver", "correct": false}, {"label": "C", "text": "Muscles of bodybuilders", "correct": true}, {"label": "D", "text": "Bone marrow after bleeding", "correct": false}], "correct_answer": "C. Muscles of bodybuilders", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Muscles of bodybuilders The skeletal muscles of bodybuilders undergo hypertrophy and NOT hyperplasia because skeletal muscles are permanent cells which are not capable of dividing . So, when bodybuilders exercise, then, ‘iron pumping’ leads to an increase in the size of skeletal muscles leading to hypertrophy. Hence, the correct option is C .</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an i ncrease in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an increase in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Metaplasia refers to a Change in the phenotype of cells Types of metaplasia: Epithelial Squamous ( most common ): Eg: Chronic smoker, Vitamin A deficiency, Bile duct and pancreatic duct stones and infection, HPV causing squamous metaplasia of cervix. Columnar: Eg: Barrett’s esophagus. Connective tissue Myositis ossificans (muscle replaced by bones due to dystrophic calcification ). Atrophy refers to the Reduction in size of an organ or tissue Eg: Senile Atrophy Disuse Atrophy Denervation Atrophy Nutritional Atrophy Pressure Atrophy Lack of endocrine stimulation leading to atrophy Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . Uterus enlargement during pregnancy is an example of physiologic hyperplasia as well as hypertrophy to support the growing baby. Option: B . Liver regeneration after donation occurs due to increased proliferation from stem cells as well as hepatocyt So, this is an example of physiologic hyperplasia . Option: D. Bone marrow after bleeding is an example of physiologic hyperplasia because after bleeding, the bone marrow starts to synthesize more red blood cells to compensate for lost cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Both hypertrophy and hyperplasia are seen in", "options": [{"label": "A", "text": "Pregnant uterus", "correct": true}, {"label": "B", "text": "Enlarged heart in hypertension", "correct": false}, {"label": "C", "text": "Biceps during exercise", "correct": false}, {"label": "D", "text": "Barrett’s esophagus", "correct": false}], "correct_answer": "A. Pregnant uterus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pregnant uterus The uterus enlarges during pregnancy to accommodate the growing fetus. This occurs due to both hyperplasia as well as hypertrophy. Hence, the correct option is A.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. is incorrect because the heart is made up of cardiac muscle fibres which are permanent cells, so, can undergo only hypertrophy. Option: C. is incorrect because biceps is an example of skeletal muscle which are permanent cells and hence can undergo only hyperplasia. Option: D. is incorrect because Barrett’s esophagus is an example of metaplasia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following describes this condition most accurately?", "options": [{"label": "A", "text": "The patient is at a higher risk for prostatic cancer", "correct": false}, {"label": "B", "text": "It is an example of physiologic hyperplasia", "correct": false}, {"label": "C", "text": "The underlying condition involves a change in cell type", "correct": false}, {"label": "D", "text": "This condition occurs due to increased stimulation by androgens", "correct": true}], "correct_answer": "D. This condition occurs due to increased stimulation by androgens", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811883593-QTDP003008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>This condition occurs due to increased stimulation by androgens The figure clearly illustrates BPH e. Benign Prostatic Hyperplasia , which is commonly seen in elderly males . It is an example of hyperplasia in which there is an increase in cell number due to increased stimulation by androgens , particularly dihydrotestosterone (DHT) . So, the correct answer is option D.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an i ncrease in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Metaplasia refers to a Change in the phenotype of cells Types of metaplasia: Epithelial Squamous ( most common ): Eg: Chronic smoker, Vitamin A deficiency, Bile duct and pancreatic duct stones and infection, HPV causing squamous metaplasia of cervix. Columnar: Eg: Barrett’s esophagus. Connective tissue Myositis ossificans (muscle replaced by bones due to dystrophic calcification ). Atrophy refers to the Reduction in the size of an organ or tissue Eg: Senile Atrophy Disuse Atrophy Denervation Atrophy Nutritional Atrophy Pressure Atrophy Lack of endocrine stimulation leading to atrophy Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . The patient is at a higher risk for prostatic cancer. Incorrect , because BPH does not increase the risk of prostatic cancer . Option: B. It is an example of physiologic hyperplasia. Incorrect , because BPH is an example of pathologic hyperplasia . Option: C . The underlying condition involves a change in cell type. Incorrect because BPH involves a change in cell number . On the other hand, a change in cell type occurs in metaplasia .</p>\n<p><strong>Extraedge:</strong></p><p>Management: Static component: 5 α reductive inhibitors (Finasteride) : decreases DHT, thereby decreasing the size of the prostate Dynamic component: α 1 blocker (Tamsulosin, Terazosin) : decreases smooth muscle tone, thereby causesing symptomatic relief Other options like TURP, High-Intensity Frequency Ultrasound (HIFU), and Radiofrequency Ablation are also used.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 55-year-old postmenopausal woman presents with complaints of vaginal bleeding for 1 week. She is on hormone replacement therapy without progestin. The endometrial biopsy is performed which is shown in the image below. Which of the following statements correctly describes the condition that the patient is suffering from?", "options": [{"label": "A", "text": "It is an example of cellular dysplasia", "correct": false}, {"label": "B", "text": "It is an example of apoptosis", "correct": false}, {"label": "C", "text": "It is an example of cellular adaptation", "correct": true}, {"label": "D", "text": "It is an example of a viral infection", "correct": false}], "correct_answer": "C. It is an example of cellular adaptation", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811883704-QTDP003009IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is an example of cellular adaptation The given figure shows endometrial hyperplasia , which can be determined by the increase in the number of glands in the histology . Endometrial hyperplasia is an example of cellular adaptation which occurs in response to increased estrogen . This is made more evident by the history of HRT without progestin . Hence, the correct answer is C.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an i ncrease in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an i ncrease in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Metaplasia refers to a Change in the phenotype of cells Types of metaplasia: Epithelial Squamous ( most common ): Eg: Chronic smoker, Vitamin A deficiency, Bile duct and pancreatic duct stones and infection, HPV causing squamous metaplasia of cervix. Columnar: Eg: Barrett’s esophagus. Connective tissue Myositis ossificans (muscle replaced by bones due to dystrophic calcification ). Atrophy refers to the Reduction in the size of an organ or tissue Eg: Senile Atrophy Disuse Atrophy Denervation Atrophy Nutritional Atrophy Pressure Atrophy Lack of endocrine stimulation leading to atrophy Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A . It is an example of cellular dysplasia, which is incorrect because endometrial hyperplasia is not an example of cellular dysplasia , instead, it is an example of cellular adaptation. Option: B . It is an example of apoptosis, which is incorrect because apoptosis refers to programmed cell death . But, endometrial hyperplasia refers to an increase in the number of cells and not cell death. Option: D . It is an example of viral infection, but is incorrect because endometrial hyperplasia does not occur in response to viral infection . It usually occurs due to risk factors such as PCOS, estrogen-producing ovarian tumours, anovulatory cycles</p>\n<p><strong>Extraedge:</strong></p><p>Although hyperplasia is distinct from cancer, pathologic hyperplasia constitutes fertile soil in which cancerous proliferations may eventually arise . For instance, patients with hyperplasia of the endometrium are at increased risk for developing endometrial cancer .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Raju a 25 years young man has started lifting weights in the gym in the last 6 months his muscle size has significantly enlarged.What change has occurred in his muscle tissue?", "options": [{"label": "A", "text": "Hyperplasia of muscle tissue", "correct": false}, {"label": "B", "text": "Hypertrophy of muscles", "correct": true}, {"label": "C", "text": "Metaplasia of muscle tissue", "correct": false}, {"label": "D", "text": "Dysplasia of muscle tissue", "correct": false}], "correct_answer": "B. Hypertrophy of muscles", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hypertrophy of muscles Yes, this is the correct option because weightlifting stimulates muscle tissue and as a result of this growth of muscle contraction parts and increased glycogen storage takes place.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hyperplasia means an increase in the number of cells so this is not the answer Option: C. No here muscle tissue does not convert to another tissue type hence this can not be an answer Option: D. Dysplasia means abnormal cell and tissue development which is not seen in this case.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25 year young recently married man comes to the general practitioner with a complaint of erectile dysfunction because of which the doctor prescribed him Sildenafil 100 mg tablets (Viagra). He visits the doctor again and says that now he has a good penis erection during intercourse. Which changes did Sildenafil cause in the penis?", "options": [{"label": "A", "text": "Hyperplasia of penile cells", "correct": false}, {"label": "B", "text": "Hypertrophy of penile cells", "correct": false}, {"label": "C", "text": "Both hypertrophy and hyperplasia", "correct": false}, {"label": "D", "text": "PDE (-) promotes blood flow", "correct": true}], "correct_answer": "D. PDE (-) promotes blood flow", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above Erectile dysfunction (ED) refers to the inability of men to attain and maintain an erect penis with sufficient rigidity to allow sexual intercourse. Sildenafil doesn't stimulate the penis for hyperplasia or hypertrophy . The size of the penis increases due to the pharmacological effect of Sildenafil. Sildenafil acts by blocking phosphodiesterase 5 (PDE5), an enzyme that promotes the breakdown of cGMP , which regulates blood flow in the penis .</p>\n<p><strong>Highyeild:</strong></p><p>Sildenafil acts by blocking phosphodiesterase 5 (PDE5), an enzyme that promotes the breakdown of cGMP , which regulates blood flow in the penis . When Sildenafil inhibits the breakdown of cGMP, it causes the accumulation of cGMP and potentiates the action of Nitric Oxide . NOTE: Sildenafil should never be prescribed to patients on nitrates as it can result in severe hypotension and can precipitate angina in patients with coronary heart disease</p>\n<p><strong>Extraedge:</strong></p><p>Sildenafil is an orally active drug and does not cause priapism in most recipients. Sildenafil is ineffective in men who have lost libido or when ED is due to spinal injury or damaged nervi eregantes . Sildenafil has been shown to improve arterial oxygenation in pulmonary hypertension</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old male has difficulty in voiding the bladder and he says he has difficulty in initiation of urination and the flow of urine is not continuous. Diagnosis of Benign Prostatic Hyperplasia (BPH)was made. What are the changes that can be seen in the bladder?", "options": [{"label": "A", "text": "Hyperplasia of the smooth muscle of the bladder", "correct": false}, {"label": "B", "text": "Hypertrophy of the smooth muscle of the bladder", "correct": true}, {"label": "C", "text": "Hyperplasia of the striated muscle of the bladder", "correct": false}, {"label": "D", "text": "Hypertrophy of the striated muscle of the bladder", "correct": false}], "correct_answer": "B. Hypertrophy of the smooth muscle of the bladder", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hypertrophy of the smooth muscle of the bladder Due to chronic obstruction , the smooth muscles of the bladder have to produce more force as a result of this muscle hypertrophy takes place. The main symptoms of BPH are due to urinary obstruction caused by prostatic enlargement and stromal smooth muscle–mediated contraction. The increased resistance to urinary outflow leads to bladder hypertrophy and distention , accompanied by urine retention , this creates a reservoir for urine and is a common source of infection . NOTE: In BPH, the Prostate shows hyperplasia and Bladder shows hypertrophy . Benign prostatic hyperplasia (BPH). (A) Well-defined nodules of BPH compress the urethra into a slit-like lumen. (B) Microscopic view of a whole mount of the prostate shows nodules of hyperplastic glands on both sides of the urethra. (C) Under high power a nodule composed of hyperplastic glands with papillary epithelial infoldings is seen.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Eg: Skeletal muscles in athletes Uterus in pregnancy Breast in puberty, pregnancy, Lactation Cardiac muscle in HTN Hyperplasia refers to an increase in cell number Eg: Uterus in pregnancy Breast in puberty, pregnancy Endometrial hyperplasia (Estrogen dependant) Benign Prostatic. Hyperplasia (Testosterone) Metaplasia refers to a Change in the phenotype of the cell Types of metaplasia: Epithelial Squamous ( most common ): Eg: Chronic smoker, Vitamin A deficiency, Bile duct and pancreatic duct stones and infection, HPV causing squamous metaplasia of cervix. Columnar: Eg: Barrett’s esophagus. Connective tissue Myositis ossificans (muscle replaced by bones due to dystrophic calcification ). Atrophy refers to the Reduction in the size of an organ or tissue Eg: Senile Atrophy Disuse Atrophy Denervation Atrophy Nutritional Atrophy Pressure Atrophy Lack of endocrine stimulation leading to atrophy Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hyperplasia of the smooth muscle of the Incorrect . Hyperplasia of smooth muscles is seen in BPH Option: C. Hyperplasia of the striated muscle of the Incorrect , bladder muscles are smooth muscles . Striated muscles are skeletal muscles and are not seen in the bladder Option: D. Hypertrophy of striated muscle of the Incorrect , bladder muscles are smooth muscles . Striated muscles are skeletal muscles and are not seen in the bladder</p>\n<p><strong>Extraedge:</strong></p><p>Management: Static component: 5 α reductive inhibitors (Finasteride) : decreases DHT, thereby decreasing the size of the prostate Dynamic component: α 1 blocker (Tamsuloson, Terazosin) : decreases smooth muscle tone, thereby causing symptomatic relief Other options like TURP, High-Intensity Frequency Ultrasound (HIFU), and Radiofrequency Ablation are also used.</p>\n<p><strong>Table:</strong></p><p>BPH is characterized by the proliferation\n of benign stromal and glandular elements. DiHydro Testosterone (DHT) is the\n major hormonal stimulus for the proliferation of BPH\n affects the transition zone and thus may encroach on the urethra,\n compressing it to a slit-like orifice . NOTE: In BPH, the Prostate shows hyperplasia and the Bladder\n shows hypertrophy . Static component: 5 α reductive inhibitor s (Finasteride) . Dynamic component: α 1\nblocker (Tamsulosin, Terazosin) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 22 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding infective endocarditis except:", "options": [{"label": "A", "text": "Subacute IE is caused by organisms with lower virulence (e.g., viridans streptococci)", "correct": false}, {"label": "B", "text": "Acute endocarditis is a necrotizing and ulcerative, invasive valvular infection on a previously normal valve", "correct": false}, {"label": "C", "text": "S. viridans is the major offender in IE among intravenous drug abusers", "correct": true}, {"label": "D", "text": "Prosthetic valve endocarditis can be caused by S epidermidis", "correct": false}], "correct_answer": "C. S. viridans is the major offender in IE among intravenous drug abusers", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>S. viridans is the major offender in IE among intravenous drug abusers False , aureus is the major offender in IE among intravenous drug abusers .</p>\n<p><strong>Highyeild:</strong></p><p>Infective Endocarditis (IE): IE is a microbial infection of the heart valves or the mural endocardium that leads to the formation of vegetation composed of thrombotic debris and organisms , often associated with the destruction of the underlying cardiac tissues . Most infections are bacterial (bacterial endocarditis). Acute IE is typically caused by infection of a previously normal heart valve by a highly virulent organism (e.g., Staphylococcus aureus) that rapidly produces destructive lesions. These infections may be difficult to cure with antibiotics alone and often require surgery ; despite appropriate treatment, there can be substantial morbidity and even mortality. Subacute IE is characterized by organisms with lower virulence (e.g., viridans streptococci) that cause insidious infections of deformed valves with overall less destruction. In such cases, the disease may pursue a protracted course of weeks to months, and cures can often be achieved with antibiotics alone. Endocarditis of native but previously damaged or otherwise abnormal valves is caused most commonly (50% to 60% of cases) by Streptococcus viridans , a normal component of the oral cavity flora. In contrast, more virulent aureus organisms commonly found on the skin can infect either healthy or deformed valves and are responsible for 20% to 30% of cases overall; notably, S. aureus is the major offender in IE among intravenous drug abusers . Prosthetic valve endocarditis occurring in the 1 to 2 months after surgical implantation is typically caused by skin flora ( aureus and S. epidermidis ), and prosthetic valve infections 1 year or more after surgery tend to be streptococci and S. aureus .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Subacute IE is caused by organisms with lower virulence (e.g., viridans streptococci). Correct . Option: B. Acute endocarditis is a necrotizing and ulcerative, invasive valvular infection on a previously normal valve. Correct . Option: D. Prosthetic valve endocarditis can be caused by S. epidermidis. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>In about 10% of all cases of endocarditis, no organism can be isolated from the blood ( “culture-negative” endocarditis ); reasons include prior antibiotic therapy , difficulties in isolating the offending agent , or because deeply embedded organisms within the enlarging vegetation are not released into the blood</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following statement is true regarding vegetations of infective endocarditis except:", "options": [{"label": "A", "text": "Friable, bulky, and potentially destructive", "correct": false}, {"label": "B", "text": "Aortic and mitral valves are most commonly affected", "correct": false}, {"label": "C", "text": "Ring abscess can be seen", "correct": false}, {"label": "D", "text": "Doesn’t involve more than one valve", "correct": true}], "correct_answer": "D. Doesn’t involve more than one valve", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Doesn’t involve more than one valve False , vegetations can be single or multiple and may involve more than one valve</p>\n<p><strong>Highyeild:</strong></p><p>Vegetations on heart valves are the classic hallmark of IE ; these are friable , bulky , potentially destructive lesions containing fibrin , inflammatory cells , and bacteria or other organisms. The aortic and mitral valves are the most common sites of infection , although the valves of the right heart may also be involved, particularly in intravenous drug abusers . Vegetations can be single or multiple and may involve more than one valve ; they can occasionally erode into the underlying myocardium and produce an abscess ( ring abscess ). Vegetations are prone to embolization ; because the embolic fragments often contain virulent organisms, abscesses frequently develop where they lodge , leading to sequelae such as septic infarcts or mycotic aneurysms .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Friable, bulky, and potentially destructive. Correct . Option: B. Aortic and mitral valves are most commonly affected. Correct . Option: C. Ring abscess can be seen. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The vegetations of subacute endocarditis are associated with less valvular destruction than those of acute endocarditis, although the distinction can be subtle. Microscopically, the vegetations of subacute IE typically exhibit granulation tissue at their bases indicative of healing. With time, fibrosis, calcification, and a chronic inflammatory infiltrate can develop.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Dukes criteria are used for the diagnosis of-", "options": [{"label": "A", "text": "Rheumatic heart disease", "correct": false}, {"label": "B", "text": "Infective endocarditis", "correct": true}, {"label": "C", "text": "Nonbacterial thrombotic endocarditis", "correct": false}, {"label": "D", "text": "Libman sac disease", "correct": false}], "correct_answer": "B. Infective endocarditis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Infective endocarditis The so-called modified Duke criteria facilitate the evaluation of individuals with suspected Infective Endocarditis ( IE ) that takes into account predisposing factors, physical findings, and blood culture results. MNEMO NIC: D uke’s criteria are used for I nfective E ndocarditis ( DIE ).</p>\n<p><strong>Highyeild:</strong></p><p>Important One Liners: Endocarditis with depositions on both sides of valves? Libman Sacks endocarditis (SLE) Most common valve involved in endocarditis of any variety? Mitral except in Infective Endocarditis which shows Atrial > Mitral Small warty, friable, and sterile vegetation seen in? RHD Loosely attached vegetations with no inflammation & are sterile? Nonbacterial thrombotic endocarditis (NBTE) = Merrantic endocarditis Verrucous-like deposits which are sterile seen in? Libman Sacks Endocarditis Large, bulky, friable vegetations which are destructive to valves & are non-sterile? Infective Endocarditis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Rheumatic heart disease. Incorrect , Jones criteria is used for RHD . Option: C. Nonbacterial thrombotic endocarditis. Incorrect . Option: D. Libman sac disease. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Identify the wrong match pair about clinical features of infective endocarditis:", "options": [{"label": "A", "text": "Fever - most consistent sign", "correct": false}, {"label": "B", "text": "Roth spot- Hemorrhagic spot on palm and sole", "correct": true}, {"label": "C", "text": "Osler nodes- painful subcutaneous nodules on finger and toe", "correct": false}, {"label": "D", "text": "Janeway lesion - red painless lesion on palm and sole", "correct": false}], "correct_answer": "B. Roth spot- Hemorrhagic spot on palm and sole", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Roth spot- Hemorrhagic spot on palm and sole</p>\n<p><strong>Highyeild:</strong></p><p>Clinical Features of IE: Although fever is the most consistent sign of IE , it can be slight or absent, particularly in older adults, and the only manifestations may be nonspecific fatigue, weight loss, and a flu-like syndrome. Janeway lesions are small erythematous or hemorrhagic , macular, non-tender lesions on the palms and soles and are the consequence of septic embolic events. Osler nodes are small, tender subcutaneous nodules that develop in the pulp of the digits or occasionally more proximally in the fingers and persist for hours to several days. Roth spots are oval retinal hemorrhages with pale centers .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Fever - most consistent sign. Correct . Option: C. Osler nodes- painful subcutaneous nodules on finger and toe. Correct . Option: D. Janeway lesion - red painful lesion on palm and sole. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Crohn’s disease is associated with:", "options": [{"label": "A", "text": "NOD 2", "correct": true}, {"label": "B", "text": "NKG2D", "correct": false}, {"label": "C", "text": "NSP 4", "correct": false}, {"label": "D", "text": "JAK2", "correct": false}], "correct_answer": "A. NOD 2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NOD 2 Crohn's disease is associated with NOD2 , which is also known as the CARD15 gene. NOD2 encodes for a protein involved in the innate immune system that recognizes bacterial components and triggers an inflammatory response. (activates signaling events, including the NF-κB pathway) Mutations in the NOD2 gene have been found to be more common in individuals with Crohn's disease compared to the general population</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. NKG2D: It is a receptor expressed on the surface of natural killer cells and some T cells. It plays a role in recognizing and eliminating cells that express stress-induced proteins, such as those found on tumor cells. Option: C .NSP4: It is a protein produced by rotaviruses that is involved in viral replication and pathogenesis. Option: D. JAK 2: Mutation is associated with polycythemia vera.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old male presents with blood and mucus in his stools for the past month, along with abdominal pain and cramping. Barium enema shows a lead-pipe appearance. Which of the following is more specifically seen in this condition?", "options": [{"label": "A", "text": "Cryptitis", "correct": false}, {"label": "B", "text": "Creeping fat", "correct": false}, {"label": "C", "text": "Crypt branching", "correct": false}, {"label": "D", "text": "Pseudopolyposis", "correct": true}], "correct_answer": "D. Pseudopolyposis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pseudopolyposis The given clinical scenario with findings of lead-pipe appearance on Barium enema is suggestive of Ulcerative colitis. Pseudopolyposis is a characteristic feature of Ulcerative colitis , which refers to the formation of multiple polyp-like growths of inflamed mucosa in the colon. These growths are not true polyps, but rather a result of the repeated cycles of inflammation and healing in the mucosa.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of Ulcerative colitis Continuous inflammation of the mucosal layer of the colon and rectum Crypt distortion , irregular shape, and shortened Infiltration of immune cells , such as lymphocytes, plasma cells, and eosinophils Ulceration, abscess formation, erosions, and tissue loss Cryptitis and crypt abscesses Basal plasmacytosis Loss of goblet cells Neutrophil infiltration Backwash ileitis (inflammation of the lower part of the small intestine) Pseudopolyps</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Cryptitis: It is the inflammation of crypts in the lining of the colon and can be seen in both Ulcerative colitis and Crohn's disease. Option:B. Creeping fat: Aka fat wrapping, is a characteristic feature of Crohn's disease, where inflamed bowel segments are covered by mesenteric fat. Option:C. Crypt branching: It is a nonspecific finding and can be seen in both Ulcerative colitis and Crohn's disease.</p>\n<p><strong>Extraedge:</strong></p><p>6 P’s of Ulcerative Colitis Pinpoint ulcers Pipestem colon Pseudopolyposis Pus cells in lamina propria Panth cell meta plasma P-ANCA positivity</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is an extraintestinal manifestation associated with Crohn's disease?", "options": [{"label": "A", "text": "Erythema nodosum", "correct": false}, {"label": "B", "text": "Uveitis", "correct": false}, {"label": "C", "text": "Kidney stones", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Erythema nodosum, uveitis, and kidney stones are all extraintestinal manifestations of IBD</p>\n<p><strong>Highyeild:</strong></p><p>Extra-intestinal manifestation of Inflammatory bowel diseases Both Ulcerative colitis and Cronh’s disease ● Rash: Pyoderma gangrenosum, Erythema nodosum ● Eye inflammation: Episcleritis, uveitis ● Oral ulceration: Aphthous stomatitis ● Arthritis: Migratory polyarthritis, sacroiliitis, ankylosing spondylitis ● Clubbing of fingertips Specific to Cronh’s disease ● Kidney stones ● Gallstones Specific to ulcerative colitis ● Primary sclerosing cholangitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following would be the best morphological feature to distinguish ulcerative colitis from Crohn’s disease:", "options": [{"label": "A", "text": "Diffuse distributions of pseudopolyps", "correct": true}, {"label": "B", "text": "Mucosal edema", "correct": false}, {"label": "C", "text": "Crypt abscesses", "correct": false}, {"label": "D", "text": "Lymphoid aggregates in the mucosa", "correct": false}], "correct_answer": "A. Diffuse distributions of pseudopolyps", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Diffuse distributions of pseudopolyps Pseudopolyps are seen only in UC. Isolated islands of regenerating mucosa often bulge into the lumen to create pseudopolyps, and the tips of these polyps may fuse to create mucosal bridges</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Options:B,C,D: Mucosal edema, crypt abscesses, and lymphoid aggregates can be seen in both ulcerative colitis and Crohn’s disease, and are not specific enough to distinguish between the two conditions.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All the following statements are false, except:", "options": [{"label": "A", "text": "Collagenous colitis is seen in children", "correct": false}, {"label": "B", "text": "Ulcerative colitis is an acute granulomatous disease", "correct": false}, {"label": "C", "text": "Ulcerative colitis involves mucosa and submucosa", "correct": true}, {"label": "D", "text": "Necrotizing enterocolitis is an acute granulomatous disease", "correct": false}], "correct_answer": "C. Ulcerative colitis involves mucosa and submucosa", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ulcerative colitis involves mucosa and submucosa The question asked is “false-except I.e true statement” Option: C is true: Ulcerative colitis involves only the mucosa and submucosa, not the deeper layers of the intestinal wall.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Collagenous colitis is seen in children: This statement is false. Collagenous colitis is actually more commonly seen in older adults, typically over the age of 50. Option:B. Ulcerative colitis is an acute granulomatous disease: This statement is false. Ulcerative colitis is a chronic inflammatory bowel disease, not an acute granulomatous disease Option:D. Necrotizing enterocolitis is an acute granulomatous disease: This statement is false. Necrotizing enterocolitis is a disease that primarily affects premature infants and is characterized by necrosis of the intestinal wall. It is not a granulomatous disease.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most common site of regional enterprises?", "options": [{"label": "A", "text": "Colon", "correct": false}, {"label": "B", "text": "Rectum", "correct": false}, {"label": "C", "text": "Distal ileum and colon", "correct": true}, {"label": "D", "text": "Caecum", "correct": false}], "correct_answer": "C. Distal ileum and colon", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Distal ileum and colon Crohn's disease is also called regional enteritis. It mos t commonly affects the terminal ileum and cecum, but any site within the gastrointestinal tract can be involved; skip lesions are common and noncaseating granulomas also occur</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of Crohn's disease: Transmural inflammation : Inflammation involves all layers of the intestinal wall, from the inner mucosal layer to the outer serosal layer. Skip lesions : Crohn's disease can involve patchy areas of inflammation with healthy tissue in between. These areas of inflammation are known as skip lesions. Non-caseating granulomas : One of the hallmark histopathological features. These are small clusters of immune cells, such as macrophages and lymphocytes, that form in response to chronic inflammation. Crypt distortion and atrophy : Like ulcerative colitis, Crohn's disease can cause distortion and atrophy of the crypts in the intestinal mucosal layer. Fibrosis and strictures : These strictures can cause bowel obstruction and other complications. Abscesses and fistulas</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Colon: It can be involved but not the most common site. Option: B .Rectum: It can be involved but not the most common site. Option: D. Caecum: It can be involved but not the most common site.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a specific complication of ulcerative colitis?", "options": [{"label": "A", "text": "Fistulas", "correct": false}, {"label": "B", "text": "Strictures", "correct": false}, {"label": "C", "text": "Toxic megacolon", "correct": true}, {"label": "D", "text": "Perianal disease", "correct": false}], "correct_answer": "C. Toxic megacolon", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Toxic megacolon Toxic megacolon is a severe and potentially life-threatening complication of ulcerative colitis. It occurs when the colon becomes dilated and distended due to inflammation , leading to a loss of muscle tone and function. This can result in symptoms such as abdominal distension, severe pain, fever, dehydration, and shock.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Fistulas: These are abnormal connections between different organs or between an organ and the skin. They can develop as a result of inflammation in the digestive tract in Crohn's disease, causing small tunnels to form between different parts of the intestine or between the intestine and other organs. Option: B. Strictures are narrowed areas of the intestine that can cause obstruction and blockage of the digestive tract. They can occur in any part of the digestive tract affected by Crohn's disease, due to chronic inflammation and scarring of the intestinal wall. Option: D. Perianal disease, including abscesses, fistulas, and fissures, can occur in patients with Crohn's disease due to inflammation in the rectal area. These complications can lead to severe pain, difficulty with bowel movements, and recurrent infections.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following serological markers is positive for Crohn's disease?", "options": [{"label": "A", "text": "ASCA", "correct": true}, {"label": "B", "text": "p-ANCA", "correct": false}, {"label": "C", "text": "Anti-goblet cell antibody", "correct": false}, {"label": "D", "text": "Anti-dsDNA", "correct": false}], "correct_answer": "A. ASCA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>ASCA ASCA (Anti-Saccharomyces cerevisiae antibodies) is the serological marker that is positive in Crohn's disease. These antibodies are directed against a specific yeast (Saccharomyces cerevisiae) that is commonly found in the gut, and they are present in up to 60% of patients with Crohn's disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. p-ANCA: (perinuclear antineutrophil cytoplasmic antibody) is a serological marker that is more commonly associated with ulcerative colitis than Crohn's disease. Option: C. Anti-goblet cell antibody: It is more commonly associated with ulcerative colitis. Option: D. Anti-dsDNA: It is a marker for systemic lupus erythematosus (SLE), which is an autoimmune disease that can affect many different organs, including the skin, joints, kidneys, and heart.</p>\n<p><strong>Table:</strong></p><p>Serological markers in IBD Ulcerative colitis Cronh’s disease p-ANCA Anti-goblet antibody ASCA OMP-C Anti-flagellum antibody Anti-pancreatic antibody Anti-l2</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are seen in Ulcerative colitis except:", "options": [{"label": "A", "text": "Pseudopolyps", "correct": false}, {"label": "B", "text": "Skip lesions", "correct": true}, {"label": "C", "text": "Rectum involvement", "correct": false}, {"label": "D", "text": "Malabsorption", "correct": false}], "correct_answer": "B. Skip lesions", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Skip lesions The presence of multiple, separate, sharply delineated areas of disease , resulting in skip lesions , is characteristic of Crohn's disease and may help in the differentiation from ulcerative colitis.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of Ulcerative colitis Continuous inflammation of the mucosal layer of the colon and rectum Crypt distortion , irregular shape, and shortened Infiltration of immune cells , such as lymphocytes, plasma cells, and eosinophils Ulceration, abscess formation, erosions, and tissue loss Cryptitis and crypt abscesses Basal plasmacytosis Loss of goblet cells Neutrophil infiltration Backwash ileitis (inflammation of the lower part of the small intestine) Pseudopolyps</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following genetic disorder is associated with inflammatory bowel disease?", "options": [{"label": "A", "text": "Wiskott Aldrich Syndrome", "correct": false}, {"label": "B", "text": "Turner Syndrome", "correct": false}, {"label": "C", "text": "Hermansky-Pudlak syndrome", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above All of the following are associated with IBG.</p>\n<p><strong>Highyeild:</strong></p><p>Genetic diseases associated with Inflammatory Bowel Diseases: Wiskott-Aldrich Syndrome Immunodysregulation polyendocrinopathy X-linked syndrome Turner’s syndrome Glycogen storage diseases Hermansky-pudlak syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following conditions is most commonly associated with the development of a fistula?", "options": [{"label": "A", "text": "Crohn’s disease", "correct": true}, {"label": "B", "text": "Ulcerative colitis", "correct": false}, {"label": "C", "text": "Infective enterocolitis", "correct": false}, {"label": "D", "text": "Coeliac sprue", "correct": false}], "correct_answer": "A. Crohn’s disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Crohn’s disease Crohn's disease is most commonly associated with the development of a fistula. It is a type of inflammatory bowel disease characterized by transmural inflammation, which can lead to the formation of abnormal connections, or fistulas, between different parts of the gut or between the gut and other organs.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of Cronh’s disease: Transmural inflammation : Inflammation involves all layers of the intestinal wall, from the inner mucosal layer to the outer serosal layer. Skip lesions : Crohn's disease can involve patchy areas of inflammation with healthy tissue in between. These areas of inflammation are known as skip lesions. Non-caseating granulomas : One of the hallmark histopathological features.These are small clusters of immune cells, such as macrophages and lymphocytes, that form in response to chronic inflammation. Crypt distortion and atrophy : Like ulcerative colitis, Crohn's disease can cause distortion and atrophy of the crypts in the intestinal mucosal layer. Fibrosis and strictures : These strictures can cause bowel obstruction and other complications. Abscesses and fistulas</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Ulcerative colitis: It is also a type of IBD, but it is characterized by inflammation that is limited to the colon and rectum. While fistulas can occur in ulcerative colitis, they are less common than in Crohn's disease. Option: C. Infective enterocolitis: It is an infection of the intestines that can be caused by bacteria, viruses, or parasites. While certain types of infections can lead to abscess formation, which may in turn lead to fistula formation, this is a less common complication than in Crohn's disease. Option: D. Coeliac sprue: It is an autoimmune disorder that is characterized by intolerance to gluten, a protein found in wheat, barley, and rye. It is not typically associated with the formation of fistulas.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 28-year-old female presents with chronic abdominal pain, diarrhea, and weight loss. She reports having these symptoms for the past 6 months. Yellowish exudates at multiple sites were seen in colonoscopy. What is the likely diagnosis?", "options": [{"label": "A", "text": "Crohn's disease", "correct": true}, {"label": "B", "text": "Hirschsprung disease", "correct": false}, {"label": "C", "text": "Tuberculosis", "correct": false}, {"label": "D", "text": "Lymphoma", "correct": false}], "correct_answer": "A. Crohn's disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Crohn's disease The given clinical history of chronic abdominal pain, diarrhea, and weight loss, in combination with the finding of yellowish exudates at multiple site s seen in colonoscopy, is suggestive of Crohn's disease.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of Cronh’s disease: Transmural inflammation : Inflammation involves all layers of the intestinal wall, from the inner mucosal layer to the outer serosal layer. Skip lesions : Crohn's disease can involve patchy areas of inflammation with healthy tissue in between. These areas of inflammation are known as skip lesions. Non-caseating granulomas : One of the hallmark histopathological features.These are small clusters of immune cells, such as macrophages and lymphocytes, that form in response to chronic inflammation. Crypt distortion and atrophy : Like ulcerative colitis, Crohn's disease can cause distortion and atrophy of the crypts in the intestinal mucosal layer. Fibrosis and strictures : These strictures can cause bowel obstruction and other complications. Abscesses and fistulas</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Hirschsprung disease: It is a congenital disorder that affects the large intestine, leading to bowel obstruction and constipation. Option: C. Tuberculosis: It can cause granulomatous inflammation in the gastrointestinal tract, but this is usually associated with systemic symptoms such as fever, night sweats, and fatigue. The presentation and colonoscopy findings, in this case, are not consistent with tuberculosis. Option: D. Lymphoma: It can also present with gastrointestinal symptoms such as abdominal pain and diarrhea, but the finding of yellowish exudates on colonoscopy is not typical for lymphoma.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 22 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Dystrophic calcification is seen in:", "options": [{"label": "A", "text": "Milk alkali syndrome", "correct": false}, {"label": "B", "text": "Atheromatous plaque", "correct": true}, {"label": "C", "text": "Hyperparathyroidism", "correct": false}, {"label": "D", "text": "Vitamin D intoxication", "correct": false}], "correct_answer": "B. Atheromatous plaque", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Atheromatous plaque Pathologic calcification is the abnormal tissue deposition of calcium salts, together with smaller amounts of iron, magnesium, and other mineral salts. There are two forms of pathologic calcification: Dystrophic calcification Metastatic calcification</p>\n<p><strong>Highyeild:</strong></p><p>Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis . Occurs despite normal serum levels of calcium and in the absence of derangements in calcium metabolism. Metastatic calcification: Deposition of calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium metabolism . Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading to Hypercalcemia Examples ● Atheromatous plaque ● Rheumatic vegetations ● Monckeberg Medial Sclerosis ● TB lymph node ● Psammoma bodies - Foci of dystrophic calcification ● Asbestos bodies ● Vitamin D intoxication ● Parathyroid tumours ● Multiple myeloma ● Paget’s disease ● Milk alkali syndrome ● Sarcoidosis ● Renal failure ● Hypercalcemia of malignancy Stains used for Calcium: Von-Kossa stain Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Milk alkali syndrome. Metastatic Calcification . Option: C. Hyperparathyroidism. Metastatic Calcification. Option: D. Vitamin D intoxication. Metastatic Calcification .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a common site for metastatic calcification?", "options": [{"label": "A", "text": "Gastric mucosa", "correct": false}, {"label": "B", "text": "Kidney", "correct": false}, {"label": "C", "text": "Parathyroid", "correct": true}, {"label": "D", "text": "Lung", "correct": false}], "correct_answer": "C. Parathyroid", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Parathyroid Metastatic calcification is not seen in parathyroid . Metastatic calcification : It occurs in live tissue . Serum Calcium level is increased ie Hypercalcemia Abnormal Ca metabolism Sites of metastatic calcification, Interstitial tissue of: Lung Kidney Gastric mucosa Systemic arteries Pulmonary veins</p>\n<p><strong>Highyeild:</strong></p><p>Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis . Occurs despite normal serum levels of calcium and in the absence of derangements in calcium metabolism. Metastatic calcification: Deposition of calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium metabolism . Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading to Hypercalcemia Examples ● Atheromatous plaque ● Rheumatic vegetations ● Monckeberg Medial Sclerosis ● TB lymph node ● Psammoma bodies - Foci of dystrophic calcification ● Asbestos bodies ● Vitamin D intoxication ● Parathyroid tumours ● Multiple myeloma ● Paget’s disease ● Milk alkali syndrome ● Sarcoidosis ● Renal failure ● Hypercalcemia of malignancy Stains used for Calcium: Von-Kossa stain Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Gastric mucosa. Metastatic Calcification is seen . Option: B. Kidney. Metastatic Calcification is seen. Option: D. Lung. Metastatic Calcification is seen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Dystrophic calcification occurs in all except?", "options": [{"label": "A", "text": "Rheumatic heart disease", "correct": false}, {"label": "B", "text": "Lymph node", "correct": false}, {"label": "C", "text": "Normal kidney", "correct": true}, {"label": "D", "text": "Aneurysm", "correct": false}], "correct_answer": "C. Normal kidney", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Normal kidney Dystrophic calcification : Deposition of calcium at sites of cell injury and necrosis . Metastatic calcification : Deposition of calcium in normal tissues , caused by hypercalcemia .</p>\n<p><strong>Highyeild:</strong></p><p>Dystrophic calcification : It occurs in dead tissue . Serum calcium level is normal . Normal calcium metabolism. Examples: Atheromatous plaque Rheumatic vegetations TB lymph node Psammoma bodies- Foci of dystrophic calcification Asbestos bodies Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis . Occurs despite normal serum levels of calcium and in the absence of derangements in calcium metabolism. Metastatic calcification: Deposition of calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium metabolism . Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading to Hypercalcemia Examples ● Atheromatous plaque ● Rheumatic vegetations ● Monckeberg Medial Sclerosis ● TB lymph node ● Psammoma bodies - Foci of dystrophic calcification ● Asbestos bodies ● Vitamin D intoxication ● Parathyroid tumours ● Multiple myeloma ● Paget’s disease ● Milk alkali syndrome ● Sarcoidosis ● Renal failure ● Hypercalcemia of malignancy Stains used for Calcium: Von-Kossa stain Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Rheumatic heart disease. Dystrophic Calcification is seen . Option: B. Lymph node. Dystrophic Calcification is seen. Option: D. Aneurysm. Dystrophic Calcification is seen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following substances is PAS + and diastase resistant?", "options": [{"label": "A", "text": "Glycogen", "correct": false}, {"label": "B", "text": "Proteins", "correct": true}, {"label": "C", "text": "Calcium", "correct": false}, {"label": "D", "text": "Lipids", "correct": false}], "correct_answer": "B. Proteins", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Proteins Proteins are PAS+ and diastase resistant .</p>\n<p><strong>Highyeild:</strong></p><p>Sweet’s reticulin stain A silver impregnation technique that demonstrates reticular fibres . Reticulum is a support function of the body and is abundant in the liver, spleen, and kidney. In a normal liver, the fibres are well-defined strands, but necrotic and cirrhotic livers show discontinuous patterns. showing reticular fibres of the liver. Reticular fibres are stained Black and Nuclei are stained Red .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Glycogen: PAS+, diastase sensitive. Option: C. Calcium: Von Kossa, Alizarin red. Option: D. Lipids. Sudan black B, Oil red O.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Lipids are stained by?", "options": [{"label": "A", "text": "Oil red O", "correct": true}, {"label": "B", "text": "Alizarin Red", "correct": false}, {"label": "C", "text": "HMB 45", "correct": false}, {"label": "D", "text": "Both A and C", "correct": false}], "correct_answer": "A. Oil red O", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Oil red O Lipids are stained by Oil red O and Sudan black B .</p>\n<p><strong>Highyeild:</strong></p><p>Sweet’s reticulin stain A silver impregnation technique that demonstrates reticular fibres . Reticulum is a support function of the body and is abundant in the liver, spleen, and kidney. In a normal liver, the fibres are well-defined strands, but necrotic and cirrhotic livers show discontinuous patterns. showing reticular fibres of the liver. Reticular fibres are stained Black and Nuclei are stained Red .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Alizarin Red stains calcium Option: C. HMB 45 stains melanin. Option: D. Both A and C. Incorrect.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following substances is PAS+ and diastase sensitive?", "options": [{"label": "A", "text": "Proteins", "correct": false}, {"label": "B", "text": "Iron", "correct": false}, {"label": "C", "text": "Lipofuscin", "correct": false}, {"label": "D", "text": "Glycogen", "correct": true}], "correct_answer": "D. Glycogen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Glycogen Glycogen is PAS+ and diastase sensitive .</p>\n<p><strong>Highyeild:</strong></p><p>Sweet’s reticulin stain A silver impregnation technique that demonstrates reticular fibres . Reticulum is a support function of the body and is abundant in the liver, spleen, and kidney. In a normal liver, the fibres are well-defined strands, but necrotic and cirrhotic livers show discontinuous patterns. showing reticular fibres of the liver. Reticular fibres are stained Black and Nuclei are stained Red .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Proteins: PAS+ diastase resistant Option: B. Iron: Prussian blue, Perl stain Option: C. Lipofuscin: Long ZN stain.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the incorrect match for the substance and its respective stains?", "options": [{"label": "A", "text": "Melanin - Masson Fontana", "correct": false}, {"label": "B", "text": "Calcium- Von Kossa", "correct": false}, {"label": "C", "text": "Lipofuscin- Alizarin red", "correct": true}, {"label": "D", "text": "Iron- Prussian blue", "correct": false}], "correct_answer": "C. Lipofuscin- Alizarin red", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lipofuscin- Alizarin red Lipofuscin - Long ZN stain . Calcium - Von Kossa, Alizarin red . Iron- Perl stain, Prussian blue Melanin- Masson Fontana, HMB 45 Lipids- Sudan black B, Oil red O Proteins- PAS+ and diastase resistant Glycogen- PAS+, diastase sensitive</p>\n<p><strong>Highyeild:</strong></p><p>Sweet’s reticulin stain A silver impregnation technique that demonstrates reticular fibres . Reticulum is a support function of the body and is abundant in the liver, spleen, and kidney. In a normal liver, the fibres are well-defined strands, but necrotic and cirrhotic livers show discontinuous patterns. showing reticular fibres of the liver. Reticular fibres are stained Black and Nuclei are stained Red .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Melanin - Masson Fontana. Correct . Option: B. Calcium- Von kossa. Correct . Option: D. Iron- Prussian blue. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding foam cells except?", "options": [{"label": "A", "text": "These are cholesterol-laden macrophages", "correct": false}, {"label": "B", "text": "It can be seen as an intracellular vacuole", "correct": false}, {"label": "C", "text": "It causes steatosis of the liver", "correct": true}, {"label": "D", "text": "Both A and B", "correct": false}], "correct_answer": "C. It causes steatosis of the liver", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It causes steatosis of the liver The terms steatosis and fatty change describe abnormal accumulations of triglycerides within parenchymal cells. Fatty change is often seen in the liver because it is the major organ involved in fat metabolism , but it is also seen in the heart, muscles, and kidneys . In higher-income nations, the most common causes of significant fatty change in the liver (fatty liver) are alcohol abuse and nonalcoholic fatty liver disease, which is often associated with diabetes and obesity. Fatty liver. High-power detail of fatty change of the liver. In most cells, the well-preserved nucleus is squeezed into the displaced rim of cytoplasm about the fat vacuole. (Courtesy Dr. James Crawford, Department of Pathology, Hofstra Northwell School of Medicine, NY.)</p>\n<p><strong>Highyeild:</strong></p><p>Lipofuscin is an insoluble pigment, also known as lipochrome or wear-and-tear pigment. Lipofuscin is composed of polymers of lipids and phospholipids in complex with protein . It is derived through lipid peroxidation of polyunsaturated lipids of intracellular membranes . In tissue sections, it appears as a yellow-brown , finely granular cytoplasmic, often perinuclear pigment . It is a telltale sign of free radical injury and lipid peroxidation . It is seen in cells undergoing slow, regressive changes and is particularly prominent in the liver and heart of ageing patients or patients with severe malnutrition and cancer cachexia . NOTE: Lipofuscin is not injurious to the cell or its functions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. These are cholesterol-laden macrophages. True . Option: B. It can be seen as an intracellular vacuole. True . Option: D. Both A and B. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Myelin figures are disintegrated products of which substance?", "options": [{"label": "A", "text": "Proteins", "correct": false}, {"label": "B", "text": "Melanin", "correct": false}, {"label": "C", "text": "Phospholipid", "correct": true}, {"label": "D", "text": "Glycogen", "correct": false}], "correct_answer": "C. Phospholipid", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Phospholipid Phospholipids are components of the myelin figures found in necrotic cells .</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy include the following: Plasma membrane alterations, such as blebbing, blunting, and loss of microvilli . Mitochondrial changes, including swelling and the appearance of small amorphous densities . Accumulation of “myelin figures” in the cytosol composed of phospholipids derived from damaged cellular membranes. Dilation of the ER, with a detachment of polysomes . Nuclear alterations, with disaggregation of granular and fibrillar elements.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Proteins. Incorrect . Option: B. Melanin. Incorrect . Option: D. Glycogen. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Niemann Pick disease is characterised by lysosomal accumulation of sphingomyelin due to an inherited deficiency of sphingomyelinase. Sphingomyelin is a ubiquitous component of cellular (including organellar) membranes, and so the enzyme deficiency blocks the degradation of the lipid, resulting in its progressive accumulation within lysosomes . Affected cells become enlarged, due to the distention of lysosomes with sphingomyelin and cholesterol. Innumerable small vacuoles of relatively uniform size are created. Electron microscopy shows that the vacuoles are engorged secondary lysosomes that contain membranous cytoplasmic bodies resembling concentric lamellated myelin figures, sometimes called zebra bodies. Niemann-Pick disease in liver. The hepatocytes and Kupffer cells have a foamy, vacuolated appearance due to deposition of lipids. (Courtesy Dr. Arthur Weinberg, Department of Pathology, University of Texas Southwestern Medical Center, Dallas, Tex.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are the features of dystrophic calcification except?", "options": [{"label": "A", "text": "Occur in dead and degenerated cells", "correct": false}, {"label": "B", "text": "Organ dysfunction is seen", "correct": false}, {"label": "C", "text": "Serum calcium is increased", "correct": true}, {"label": "D", "text": "Psammoma bodies are seen", "correct": false}], "correct_answer": "C. Serum calcium is increased", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serum calcium is increased Dystrophic calcification : Deposition of calcium at sites of cell injury and necrosis . Metastatic calcification : Deposition of calcium in normal tissues , caused by hypercalcemia . Dystrophic calcification: It occurs in dead tissue . Serum calcium level is normal . Normal calcium metabolism. Examples: Atheromatous plaque Rheumatic vegetations TB lymph node Psammoma bodies - Foci of dystrophic calcification Asbestos bodies</p>\n<p><strong>Highyeild:</strong></p><p>Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis . Occurs despite normal serum levels of calcium and in the absence of derangements in calcium metabolism. Metastatic calcification: Deposition of calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium metabolism . table,tr,th,td {border:1px solid black;} Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading to Hypercalcemia Examples ● Atheromatous plaque ● Rheumatic vegetations ● Monckeberg Medial Sclerosis ● TB lymph node ● Psammoma bodies - Foci of dystrophic calcification ● Asbestos bodies ● Vitamin D intoxication ● Parathyroid tumours ● Multiple myeloma ● Paget’s disease ● Milk alkali syndrome ● Sarcoidosis ● Renal failure ● Hypercalcemia of malignancy Stains used for Calcium: Von-Kossa stain Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Occurs in dead and degenerated cells. Seen with Dystrophic Calcification . Option: B. Organ dysfunction is seen. Seen with Dystrophic Calcification . Option: D. Psammoma bodies are seen. Seen with Dystrophic Calcification .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are examples of Metastatic calcification except?", "options": [{"label": "A", "text": "Multiple myeloma", "correct": false}, {"label": "B", "text": "Sarcoidosis", "correct": false}, {"label": "C", "text": "Vitamin D toxicity", "correct": false}, {"label": "D", "text": "Atheromatous plaque", "correct": true}], "correct_answer": "D. Atheromatous plaque", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Atheromatous plaque Metastatic calcification is not seen with Atheromatous plaque , Dystrophic calcification is seen with Atheromatous plaque . Metastatic calcification : It occurs in live tissue . Serum Calcium level is increased ie Hypercalcemia Abnormal Ca metabolism Examples of Metastatic calcification are: Vitamin D intoxication Parathyroid tumours Multiple myeloma Paget’s disease Milk alkali syndrome Sarcoidosis Renal failure Hypercalcemia of malignancy</p>\n<p><strong>Highyeild:</strong></p><p>Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis . Occurs despite normal serum levels of calcium and in the absence of derangements in calcium metabolism. Metastatic calcification: Deposition of calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium metabolism . table,tr,th,td {border:1px solid black;} Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading to Hypercalcemia Examples ● Atheromatous plaque ● Rheumatic vegetations ● Monckeberg Medial Sclerosis ● TB lymph node ● Psammoma bodies - Foci of dystrophic calcification ● Asbestos bodies ● Vitamin D intoxication ● Parathyroid tumours ● Multiple myeloma ● Paget’s disease ● Milk alkali syndrome ● Sarcoidosis ● Renal failure ● Hypercalcemia of malignancy Stains used for Calcium: Von-Kossa stain Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Gastric mucosa. Metastatic Calcification is seen . Option: B. Kidney. Metastatic Calcification is seen. Option: D. Lung. Metastatic Calcification is seen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following substances is responsible for 'Brown Atrophy'?", "options": [{"label": "A", "text": "Melanin", "correct": false}, {"label": "B", "text": "Lipofuscin", "correct": true}, {"label": "C", "text": "Hemosiderin", "correct": false}, {"label": "D", "text": "Lipids", "correct": false}], "correct_answer": "B. Lipofuscin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lipofuscin Lipofuscin when deposited in cells, imparts yellow-brown colour to the cells . It is called Brown Atrophy .</p>\n<p><strong>Highyeild:</strong></p><p>Lipofuscin is an insoluble pigment, also known as lipochrome or wear-and-tear pigment. Lipofuscin is composed of polymers of lipids and phospholipids in complex with protein . It is derived through lipid peroxidation of polyunsaturated lipids of intracellular membranes . In tissue sections, it appears as a yellow-brown , finely granular cytoplasmic, often perinuclear pigment . It is a telltale sign of free radical injury and lipid peroxidation . It is seen in cells undergoing slow, regressive changes and is particularly prominent in the liver and heart of ageing patients or patients with severe malnutrition and cancer cachexia . NOTE: Lipofuscin is not injurious to the cell or its functions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Melanin Incorrect . Option: C. Hemosiderin. Incorrect . Option: D. Lipids. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding lipofuscin except?", "options": [{"label": "A", "text": "Telltale sign of free radical injury", "correct": false}, {"label": "B", "text": "It is deposited in the nucleus", "correct": true}, {"label": "C", "text": "It is also called wear and tear pigment", "correct": false}, {"label": "D", "text": "Lipofuscin is not injurious to the cell or its functions", "correct": false}], "correct_answer": "B. It is deposited in the nucleus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is deposited in the nucleus Its site of deposition is perinuclear . Lipofuscin when deposited in cells, imparts a yellow-brown colour to the cells . It is called Brown Atrophy .</p>\n<p><strong>Highyeild:</strong></p><p>Lipofuscin is an insoluble pigment, also known as lipochrome or wear-and-tear pigment. Lipofuscin is composed of polymers of lipids and phospholipids in complex with protein . It is derived through lipid peroxidation of polyunsaturated lipids of intracellular membranes . In tissue sections, it appears as a yellow-brown , finely granular cytoplasmic, often perinuclear pigment . It is a telltale sign of free radical injury and lipid peroxidation . It is seen in cells undergoing slow, regressive changes and is particularly prominent in the liver and heart of ageing patients or patients with severe malnutrition and cancer cachexia . NOTE: Lipofuscin is not injurious to the cell or its functions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Telltale sign of free radical injury. Correct . Option: C. It is also called wear and tear pigment. Correct . Option: D. Lipofuscin is not injurious to the cell or its functions. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old male who is a chronic alcoholic presents with jaundice and right hypochondrial tenderness. A liver biopsy showed the following findings. Which of the following intermediate filaments may be characteristically present in the marked finding in this patient’s biopsy results?", "options": [{"label": "A", "text": "Desmin", "correct": false}, {"label": "B", "text": "Vimentin", "correct": false}, {"label": "C", "text": "Chromogranin", "correct": false}, {"label": "D", "text": "Cytokeratin", "correct": true}], "correct_answer": "D. Cytokeratin", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686814849017-QTDP014015IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cytokeratin Diagnosis: Alcoholic hepatitis . Mallory hyaline is present in the hepatocyte (marked). Immunostaining for Cytokeratin 8 and 18 is positive with Mallory-Denk bodies/ Mallory hyaline . Mallory hyaline may reflect a failed attempt to sequester and degrade damaged cytoplasmic proteins.</p>\n<p><strong>Highyeild:</strong></p><p>Do not confuse alcoholic steatosis with alcoholic hepatitis . Alcoholic hepatitis refers to liver inflammation and fibrosis which occurs in patients with alcoholic liver disease and shows the following microscopic findings : Ballooned hepatocytes which are injured, swollen hepatocytes with cleared-out cytoplasm and cytoskeletal damage , which when extensive, results in the formation of Mallory hyaline , tangled skeins of intermediate filaments such as keratin 8 and keratin 18 . Inflammation and necrosis : Neutrophils are generally more prominent in alcoholic hepatitis than in NASH. Perivenular/pericellular fibrosis: Perisinusoidal, fibrosis with a “chicken wire” appearance . Alcoholic steatosis and fibrosis. A mix of small and large fat droplets (seen as clear vacuoles) is most prominent around the central vein and extends outward to the portal tracts. Some fibrosis (stained blue) is present in a characteristic perisinusoidal chicken wire pattern. (Masson trichrome stain). (Courtesy Dr. Elizabeth Brunt, Washington University, St. Louis, Mo.) (A) Alcoholic hepatitis with clustered inflammatory cells marking the site of a necrotic hepatocyte. Mallory hyaline is present in another hepatocyte (arrow). (B) Alcoholic hepatitis with many ballooned hepatocytes (arrowheads). Clusters of inflammatory cells are also present; inset shows immunostaining for keratins 8 and 18 (brown), with most hepatocytes, including those with fat vacuoles, showing normal cytoplasmic staining, but in the ballooned cell (arrow) the ubiquinated keratins are collapsed into Mallory hyaline, leaving the cytoplasm \"empty.\" (Courtesy Dr. Elizabeth Brunt, Washington University, St. Louis, Mo.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Desmin - positive in Muscle Tumours like rhabdomyosarcoma . Option: B. Vimentin - positive in mesenchymal tumours/ sarcomas and many other tumours. Option: C. Chromogranin – positive for small cell carcinoma of lung and carcinoid tumours .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old female patient was referred to the oncology department for evaluation of a mole on her arm. A skin biopsy of the mole showed the following. Which of the following stains can be used to stain the intracellular accumulation present in this patient?", "options": [{"label": "A", "text": "Masson- Fontana stain", "correct": true}, {"label": "B", "text": "Orcein", "correct": false}, {"label": "C", "text": "Toluidine blue", "correct": false}, {"label": "D", "text": "Masson Trichrome", "correct": false}], "correct_answer": "A. Masson- Fontana stain", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686814849836-QTDP014016IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Masson- Fontana stain The patient suffers from malignant melanoma . Masson-Fontana is the stain used to stain melanin pigment.</p>\n<p><strong>Highyeild:</strong></p><p>Melanoma is the most deadly of all skin cancers and is strongly linked to acquired mutations caused by exposure to UV radiation in sunlight . Melanoma is a highly aggressive malignancy , the risk of spread is predicted by several tumour characteristics, particularly the vertical thickness of excised tumours . The most important warning signs, sometimes called the ABCDEs of melanoma are: A symmetry Irregular B orders Variegated C olor Increasing D iameter E volution or change over time, especially if rapid.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Orcein - Stains copper binding antigen and elastic tissue. Option: C. Toluidine blue-stains mast cells and basophils . Option: D. Masson Trichrome - Stains Collagen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 25 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 45-year-old man comes to the medicine OPD with the following complaints. He says that after having a meal he always feels heartburn. He says that it feels like some food particles literally return from the stomach into the oesophagus. You are suspecting GERD. What can be the consequences of this and what is the cause for the same?", "options": [{"label": "A", "text": "Barrett's esophagus due to metaplasia of lower esophageal epithelium", "correct": true}, {"label": "B", "text": "Barrett's esophagus due to hyperplasia of lower esophageal epithelium", "correct": false}, {"label": "C", "text": "Achalasia due to sphincter hypertrophy", "correct": false}, {"label": "D", "text": "Achalasia due to sphincter hyperplasia", "correct": false}], "correct_answer": "A. Barrett's esophagus due to metaplasia of lower esophageal epithelium", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Barrett's esophagus due to metaplasia of lower esophageal epithelium Barrett's esophagus is a complication of chronic GERD that is characterized by intestinal metaplasia within the esophageal squamous mucosa . The incidence of Barrett's esophagus is rising, and it is estimated to occur in as many as 10% of individuals with symptomatic GERD . Barrett esophagus is most common in white males and typically presents between 40 and 60 years of age. The greatest concern in Barrett's esophagus is that it confers an increased risk of esophageal adenocarcinoma, however, most individuals with Barrett’s esophagus do not develop esophageal tumours . NOTE: Barrett’s esophagus is not cancerous, it is precancerous .</p>\n<p><strong>Highyeild:</strong></p><p>Barrett's esophagus can be recognized as tongues of red, velvety mucosa extending upward from the gastroesophageal junction. Histologic appearance of the gastroesophageal junction in Barrett's Note the transition between esophageal squamous mucosa (left) and Barrett metaplasia, with abundant metaplastic goblet cells which are seen as mucin-filled glands (right). Goblet cells are diagnostic of Barrett’s.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. No, it's Metaplasia, not hyperplasia. Option: C & D. Achalasia with GERD is very less likely.</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis of Barrett’s requires endoscopy and biopsy showing evidence of metaplastic columnar mucosa above gastroesophageal junction and regular follow-up with endoscopy and biopsy to check for progression to Adenocarcinoma . Management of Barrett’s involves the use of Proton Pump Inhibitors . Goblet cells are the hallmark of the Intestinal type of metaplasia . These contain mucin and can be stained with Mucicarmine stain and Alicante blue (better) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All the statements regarding cellular adaptations are true. Except:", "options": [{"label": "A", "text": "The most common metaplasia is Barrett's esophagus", "correct": true}, {"label": "B", "text": "If stress is removed hypertrophy is reversible", "correct": false}, {"label": "C", "text": "Uterus during pregnancy is an example of both hypertrophy and hyperplasia", "correct": false}, {"label": "D", "text": "Autophagy can be responsible for atrophy", "correct": false}], "correct_answer": "A. The most common metaplasia is Barrett's esophagus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The most common metaplasia is Barrett's esophagus Cell adaptation Hypertrophy Hyperplasia Metaplasia Atrophy Let's see the options one by one Option: A. This statement is false . Because most common epithelial metaplasia is columnar to squamous called Squamous metaplasia which occurs in the respiratory tract in response to chronic irritation . In the habitual cigarette smoker , the normal ciliated columnar epithelial cells of the trachea and bronchi are often replaced by stratified squamous epithelial cells. Metaplasia of columnar to squamous epithelium. (A) Schematic diagram. (B) Metaplasia of columnar epithelium (left) to squamous epithelium (right) in a bronchus (as often occurs with smoking).</p>\n<p><strong>Highyeild:</strong></p><p>The following are seen in cancer cells : Anaplasia refers to a l ack of differentiation . Pleomorphism refers to variations in the size and shape of the cell . Hyperchromasia coarsest clumped and darkly stained chromatin with irregular nuclei . Anaplastic tumor showing cellular and nuclear variation in size and shape. The prominent cell in the center field has an abnormal tripolar spindle.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. If stress is removed hypertrophy is reversible .This statement is true . Option: C. Uterus during pregnancy is an example of both hypertrophy and hyperplasia .This statement is true . Option: D. Autophagy can be responsible for atrophy . Autophagy means Self-eating . Atrophy occurs due to the degradation of cellular proteins by the Ubiquitin Proteasome pathway . This pathway removes damaged and misfolded proteins. This pathway is also thought to be responsible for the accelerated proteolysis seen in a variety of catabolic conditions, including cancer cachexia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "During a forensic autopsy of the suspicious death of a 5-year-old child, it was found that it was a murder and was done by smothering. If we plot the sequence of changes that had occurred in cells of the body between the onset of the process till the death of the cells. What would be the first event which would have taken place?", "options": [{"label": "A", "text": "Cellular swelling", "correct": false}, {"label": "B", "text": "Mitochondrial density formation", "correct": false}, {"label": "C", "text": "Chromatin condensation", "correct": false}, {"label": "D", "text": "Cessation of oxidative phosphorylation and decreased ATPs", "correct": true}], "correct_answer": "D. Cessation of oxidative phosphorylation and decreased ATPs", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cessation of oxidative phosphorylation and decreased ATPs Smothering causes hypoxic hypoxia so the delivery of oxygen to tissue is reduced . As intracellular oxygen tension falls, oxidative phosphorylation fails and ATP generation decreases, this loss of ATP results initially in reversible cell injury and later in cell death by necrosis . Ischemia, which is the most common cause of cell injury in clinical medicine, results from hypoxia-induced by reduced blood flow, most often due to mechanical arterial obstruction .</p>\n<p><strong>Highyeild:</strong></p><p>Restoration of blood flow to ischemic tissues can promote recovery of cells if they are reversibly injured but can also paradoxically exacerbate cell injury and cause cell death. As a consequence, reperfused tissues may sustain a loss of viable cells in addition to those that are irreversibly damaged by ischemia. This process is called ischemia-reperfusion .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cellular swelling . It occurs after cessation of Na-K ATPase activity . Due to this excess sodium accumulates inside the cell and water follows sodium. Option: B & C. Both these changes are seen later in cell injury.</p>\n<p><strong>Extraedge:</strong></p><p>Mammalian cells have developed protective responses to deal with hypoxic stress. The best-defined of these is the induction of a transcription factor called hypoxia-inducible factor-1 (HIF-1), which promotes new blood vessel formation, stimulates cell survival pathways, and enhances glycolysis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the mechanism of the adaptive change seen in this Image of a chronic smoker?", "options": [{"label": "A", "text": "Decreased workload", "correct": false}, {"label": "B", "text": "Increased production of cellular proteins", "correct": false}, {"label": "C", "text": "Increased growth hormone", "correct": false}, {"label": "D", "text": "Due to a change in stem cell differentiation", "correct": true}], "correct_answer": "D. Due to a change in stem cell differentiation", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811782590-QTDP002004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Due to a change in stem cell differentiation In this image, epithelial metaplasia is seen. Epithelial metaplasia seen here is columnar to squamous . It occurs in the respiratory tract in response to chronic irritation . In the habitual cigarette smoker , the normal ciliated columnar epithelial cells of the trachea and bronchi are often replaced by stratified squamous epithelial cells . It is due to changes in stem cell differentiation.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from a decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Decreased workload , causes Atrophy, not metaplasia. Option: B. Increased production of cellular proteins , may cause hypertrophy . Option: C. Increased growth hormone , may cause hyperplasia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25-year-old alcoholic male presented to the OPD with tenderness over the right hypochondrium. A liver biopsy was taken and the histopathological image is shown below. Which of the following stains can be used by the pathologist to demonstrate the disease?", "options": [{"label": "A", "text": "Von Kossa", "correct": false}, {"label": "B", "text": "Prussian blue", "correct": false}, {"label": "C", "text": "Oil red O", "correct": true}, {"label": "D", "text": "Rubeanic acid", "correct": false}], "correct_answer": "C. Oil red O", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811782669-QTDP002005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Oil red O The patient has tender fatty liver or steatosis . The terms steatosis and fatty change describe abnormal accumulations of triglycerides within parenchymal cells. Fatty change is often seen in the liver because it is the major organ involved in fat metabolism . Steatosis can be macrovesicular and microvesicular, although both are seen in alcoholic liver disease, macrovesicular steatosis is the predominant form . The stain for lipids is Oil red O .</p>\n<p><strong>Highyeild:</strong></p><p>Do not confuse alcoholic steatosis with alcoholic hepatitis . Alcoholic hepatitis refers to liver inflammation and fibrosis which occurs in patients with alcoholic liver disease and shows the following microscopic findings : Ballooned hepatocytes are injured, swollen hepatocytes with cleared-out cytoplasm and cytoskeletal damage , which when extensive, results in the formation of Mallory hyaline , tangled skeins of intermediate filaments such as keratin 8 and keratin 18 . Inflammation and necrosis : Neutrophils are generally more prominent in alcoholic hepatitis than in NASH. Perivenular/pericellular fibrosis: Perisinusoidal, fibrosis with a “chicken wire” appearance . Alcoholic steatosis and fibrosis. A mix of small and large fat droplets (seen as clear vacuoles) is most prominent around the central vein and extends outward to the portal tracts. Some fibrosis (stained blue) is present in a characteristic perisinusoidal chicken wire pattern. (Masson trichrome stain). (Courtesy Dr. Elizabeth Brunt, Washington University, St. Louis, Mo.) (A) Alcoholic hepatitis with clustered inflammatory cells marking the site of a necrotic hepatocyte. Mallory hyaline is present in another hepatocyte (arrow). (B) Alcoholic hepatitis with many ballooned hepatocytes (arrowheads). Clusters of inflammatory cells are also present; inset shows immunostaining for keratins 8 and 18 (brown), with most hepatocytes, including those with fat vacuoles, showing normal cytoplasmic staining, but in the ballooned cell (arrow) the ubiquinated keratins are collapsed into Mallory hyaline, leaving the cytoplasm \"empty\" (Courtesy Dr. Elizabeth Brunt, Washington University, St. Louis, Mo.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: Von K ossa – Stains Calcium . Option: B. Prussian blue/ Perls stain - Stains Iron/ Hemosiderin . Option: D. Rubeanic acid - Stains Copper .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are features of immunity given by MALT except-", "options": [{"label": "A", "text": "Very specific to the antigen", "correct": true}, {"label": "B", "text": "Always active", "correct": false}, {"label": "C", "text": "Memory is absent", "correct": false}, {"label": "D", "text": "Limited diversity of antigens", "correct": false}], "correct_answer": "A. Very specific to the antigen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Very specific to the antigen MALT is not specific to antigens as it is a part of innate immunity . MALT . Mucosa-Associated Lymphoid Tissue initiates immune responses to specific antigens encountered along all mucosal surfaces . MALT is a part of innate immunity . Innate immunity (also called natural, or native, immunity) refers to intrinsic mechanisms that are poised to react immediately , and thus constitute the first line of defense .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Always active. True . Option: C. Memory is absent. True . Option: D. Limited diversity of antigens. True .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The lag phase is seen in-", "options": [{"label": "A", "text": "Innate immunity", "correct": false}, {"label": "B", "text": "Adaptive immunity", "correct": true}, {"label": "C", "text": "Complement-mediated immunity", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. Adaptive immunity", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adaptive immunity The lag phase is the period required fo r the activation o f the immune system . As innate immunity is present since birth and active always , thus it does not require the lag phase but adaptive immunity is active onl y post-exposure to antigen, so it has a longer lag phase .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Innate immunity. Innate immunity doesn’t have a lag phase . Option: C. Complement system. The complement system is a part of innate immunity and thus doesn’t show a lag phase . Option: D. All. Incorrect option .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are the parts of adaptive immunity except-", "options": [{"label": "A", "text": "B lymphocytes", "correct": false}, {"label": "B", "text": "T lymphocytes", "correct": false}, {"label": "C", "text": "NK cells", "correct": true}, {"label": "D", "text": "Plasma cells", "correct": false}], "correct_answer": "C. NK cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NK cells NK cells are a part of innate immunity .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. B lymphocytes. Part of adaptive immunity . Option: B. T lymphocytes. Part of adaptive immunity . Option: D. Plasma cells. Part of adaptive immunity .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Humoral immunity is a part of-", "options": [{"label": "A", "text": "Innate immunity", "correct": false}, {"label": "B", "text": "Adaptive immunity", "correct": true}, {"label": "C", "text": "Both", "correct": false}, {"label": "D", "text": "It is a separate entity", "correct": false}], "correct_answer": "B. Adaptive immunity", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adaptive immunity There are two types of adaptive immunity: Humoral immunity , which protects against extracellular microbes and their toxins Cell-mediated (or cellular) immunity , is responsible for defense against intracellular microbes and cancers. Humoral immunity is mediated by B (bone marrow-derived) lymphocytes and their secreted products, antibodies (also called immunoglobulins, Ig) Cellular immunity is mediated by T (thymus-derived) lymphocytes .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Innate immunity. Incorrect option . Option: B. Both. Incorrect option . Option: D. It is a separate entity. Incorrect option .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following lymphocytes are found in the maximum number in peripheral blood?", "options": [{"label": "A", "text": "B lymphocytes", "correct": false}, {"label": "B", "text": "T lymphocytes", "correct": true}, {"label": "C", "text": "NK cells", "correct": false}, {"label": "D", "text": "All are in equal numbers", "correct": false}], "correct_answer": "B. T lymphocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>T lymphocytes T lymphocytes develop in the thymus from precursors that arise from hematopoietic stem cells (HSCs). Mature T cells are found in the blood, where they constitute 60% to 70% of lymphocytes , and in T-cell zones of secondary lymphoid organs .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Optio n: A. B lymphocytes. B lymphocytes develop from precursors in the bone marrow . Mature B cells constitute 10% to 20% of lymphocytes in the blood and are also present in peripheral lymphoid tissues such as lymph nodes, spleen, and mucosa-associated lymphoid tissues . Option: C. NK cells. NK cells make up approximately 5% to 10% of peripheral blood lymphocytes . Option: D. All are in equal numbers. Incorrect option .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding NK cells except-", "options": [{"label": "A", "text": "It is derived from large granular lymphocytes", "correct": false}, {"label": "B", "text": "It expresses CD16 and CD56", "correct": false}, {"label": "C", "text": "CD56 is the receptor for the Fc fragment of IgG", "correct": true}, {"label": "D", "text": "Role in Antibodies dependent cytotoxic killing", "correct": false}], "correct_answer": "C. CD56 is the receptor for the Fc fragment of IgG", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD56 is the receptor for the Fc fragment of IgG CD56 is an NK cell adhesion molecule . CD16 is a receptor for the Fc fragment of IgG.</p>\n<p><strong>Highyeild:</strong></p><p>Natural Killer cells The function of NK cells is to recognize and destroy severely stressed or abnormal cells , such as virus-infected cells and tumor cells . NK cells make up approximately 5% to 10% of peripheral blood lymphocytes . NK cells express CD16, a receptor for IgG Fc tails that confers on NK cells the ability to lyse IgG-coated target cells . This phenomenon is known as antibody-dependent cellular cytotoxicity (ADCC) . The killing of target cells by NK cells is regulated by signals from activating and inhibitory receptors . Thus, these receptors enable NK cells to recognize damaged or infected cells . NK cell inhibitory receptors recognize self-class I MHC molecules, which are expressed in all healthy cells . These prevent NK cells from killing normal cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is derived from large granular lymphocytes. True for NK cells . Option: B. It expresses CD16 and CD56. True for NK cells . Option: D. Role in Antibodies dependent cytotoxic killing. True for NK cells .</p>\n<p><strong>Extraedge:</strong></p><p>Virus infection or neoplastic transformation often enhances the expression of ligands for activating receptors and at the same time reduces the expression of class I MHC molecules . As a result, when NK cells engage these abnormal cells the balance is tilted toward activation , and the infected or tumor cell is killed .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "NK cells can kill-", "options": [{"label": "A", "text": "Bacterial-infected cells", "correct": false}, {"label": "B", "text": "Tumor cells", "correct": true}, {"label": "C", "text": "Fungal-infected cells", "correct": false}, {"label": "D", "text": "Both B and C", "correct": false}], "correct_answer": "B. Tumor cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tumor cells NK cells target Tumor cells and Virus infected cells .</p>\n<p><strong>Highyeild:</strong></p><p>Natural Killer cells The function of NK cells is to recognize and destroy severely stressed or abnormal cells , such as virus-infected cells and tumor cells . NK cells make up approximately 5% to 10% of peripheral blood lymphocytes . NK cells express CD16, a receptor for IgG Fc tails that confers on NK cells the ability to lyse IgG-coated target cells . This phenomenon is known as antibody-dependent cellular cytotoxicity (ADCC) . This killing of target cells by NK cells is regulated by signals from activating and inhibitory receptors . Thus, these receptors enable NK cells to recognize damaged or infected cells . NK cell inhibitory receptors recognize self-class I MHC molecules, which are expressed in all healthy cells . These prevent NK cells from killing normal cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Bacterially infected cells. Not killed by NK cells . Option: C. Fungal infected cells. Not killed by NK cells . Option: D. Both B and C. Fungal-infected c ells are not killed by NK cells .</p>\n<p><strong>Extraedge:</strong></p><p>Virus infection or neoplastic transformation often enhances the expression of ligands for activating receptors and at the same time reduces the expression of class I MHC molecules . As a result, when NK cells engage these abnormal cells the balance is tilted toward activation , and the infected or tumor cell is killed .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pattern recognition receptors can be found in -", "options": [{"label": "A", "text": "Cell surface", "correct": false}, {"label": "B", "text": "Cytoplasm", "correct": false}, {"label": "C", "text": "In vesicles", "correct": false}, {"label": "D", "text": "Any of the above", "correct": true}], "correct_answer": "D. Any of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Any of the above</p>\n<p><strong>Highyeild:</strong></p><p>Pattern Recognition Receptors: Pattern Recognition Receptors (PRR) are located in all cellular compartments where microbes may be present : Plasma membrane receptors detect extracellular microbes Endosomal receptors detect ingested microbes Cytosolic receptors detect microbes in the cytoplasm. Types of pattern recognized: PAMP : Pathogen Associated Molecular Pattern: Present on Pathogens. DAMP : Damage Associated Molecular Pattern: Present on Necrotic cells/Damaged cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cell surface. True . Option: B. Cytoplasm. True . Option: C. In vesicles. True .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of PRR: Toll-Like Receptors (TLR) Nod Like Receptors (NLR) C-Lectin Receptors (CLR) Rig Like Receptors (RLR) Mannose Receptors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is associated with Pattern recognition receptors?", "options": [{"label": "A", "text": "PAMP and DAMP", "correct": false}, {"label": "B", "text": "Toll-like receptor", "correct": false}, {"label": "C", "text": "Nod-like receptors", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Pattern Recognition Receptors: Pattern Recognition Receptors (PRR) are located in all cellular compartments where microbes may be present : Plasma membrane receptors detect extracellular microbes Endosomal receptors detect ingested microbes Cytosolic receptors detect microbes in the cytoplasm. Types of pattern recognized: PAMP : Pathogen Associated Molecular Pattern: Present on Pathogens. DAMP : Damage Associated Molecular Pattern: Present on Necrotic cells/Damaged cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. PAMP and DAMP. Both are released by infected cells and activate T cells. Option: B. Toll-like receptor. Example of pattern recognition receptors. Option: C. Nod-like receptors. Example of pattern recognition receptors.</p>\n<p><strong>Extraedge:</strong></p><p>Examples of PRR: Toll-Like Receptors (TLR) Nod-Like Receptors (NLR) C-Lectin Receptors (CLR) Rig Like Receptors (RLR) Mannose Receptors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Toll-like receptors in humans except?", "options": [{"label": "A", "text": "It is related to Toll, a gene found in drosophila", "correct": false}, {"label": "B", "text": "Humans have 10 different types of toll-like receptors", "correct": false}, {"label": "C", "text": "It inhibits the transcription factor NF-kB", "correct": true}, {"label": "D", "text": "It stimulates the release of interferon-gamma", "correct": false}], "correct_answer": "C. It inhibits the transcription factor NF-kB", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It inhibits the transcription factor NF-kB All Toll -Like Receptors (TLRs) signal by a common pathway that culminates in the activation of two sets of transcription factors : NF-κB , which stimulates the synthesis and secretion of cytokines and the expression of adhesion molecules , both of which are critical for the recruitment and activation of leukocytes . Interferon regulatory factors (IRFs) , which stimulate the production of the antiviral cytokines , type I interferons .</p>\n<p><strong>Highyeild:</strong></p><p>Pattern Recognition Receptors: Pattern Recognition Receptors (PRR) are located in all cellular compartments where microbes may be present : Plasma membrane receptors detect extracellular microbes Endosomal receptors detect ingested microbes Cytosolic receptors detect microbes in the cytoplasm. Types of pattern recognized: PAMP : Pathogen Associated Molecular Pattern: Present on Pathogens. DAMP : Damage Associated Molecular Pattern: Present on Necrotic cells/Damaged cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is related to Toll, a gene found in drosophila. The best-known pattern recognition receptors are the TLRs, whose founding member, Toll , was discovered in Drosophila as a gene involved in the development of the fly. Option: B. Humans have 10 different types of toll-like receptors. Mammals have 10 TLRs , each recognizing a different set of microbial molecules. Option: D. It stimulates the release of interferon-gamma. True .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of PRR: Toll-Like Receptors (TLR) Nod-Like Receptors (NLR) C-Lectin Receptors (CLR) Rig Like Receptors (RLR) Mannose Receptors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following combinations of toll-like receptors and their respective ligand is correct?", "options": [{"label": "A", "text": "TLR- 5, virus", "correct": false}, {"label": "B", "text": "TLR- 2, protozoa", "correct": false}, {"label": "C", "text": "TLR- 4, gram-negative bacteria", "correct": true}, {"label": "D", "text": "TLR-9 , flagella", "correct": false}], "correct_answer": "C. TLR- 4, gram-negative bacteria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TLR- 4, gram-negative bacteria TLR Localization Ligand Sources of the ligand TLR1 Plasma membrane Triacyl lipoprotein Bacteria, mycoplasma TLR2 Plasma membrane Lipoprotein Bacteria (gram-positive), viruses, parasites, self TLR3 Endolysosome dsRNA Virus TLR4 Plasma membrane LPS Bacteria (gram-negative), viruses, self TLR5 Plasma membrane Flagellin Bacteria TLR6 Plasma membrane Diacyl lipoprotein Bacteria, viruses TLR7 (human TLR8) Endolysosome SSRNA Virus, bacteria, self TLR9 Endolysosome CpG-DNA Virus, bacteria, protozoa TLR10 Endolysosome Unknown Unknown TLR11 Plasma membrane Profilin-like molecule Protozoa All Toll-Like Receptors (TLRs) signal by a common pathway that culminates in the activation of two sets of transcription factors : NF-κB , which stimulates the synthesis and secretion of cytokines and the expression of adhesion molecules , both of which are critical for the recruitment and activation of leukocytes . Interferon regulatory factors (IRFs) , which stimulate the production of the antiviral cytokines , type I interferons .</p>\n<p><strong>Highyeild:</strong></p><p>Pattern Recognition Receptors: Pattern Recognition Receptors (PRR) are located in all cellular compartments where microbes may be present : Plasma membrane receptors detect extracellular microbes Endosomal receptors detect ingested microbes Cytosolic receptors detect microbes in the cytoplasm. Types of pattern recognized: PAMP : Pathogen Associated Molecular Pattern: Present on Pathogens. DAMP : Damage Associated Molecular Pattern: Present on Necrotic cells/Damaged cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. TLR- 5, virus. Incorrect . Option: B. TLR- 2, protozoa. Incorrect . Option: D. TLR-9, flagella. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of PRR: Toll-Like Receptors (TLR) Nod-Like Receptors (NLR) C-Lectin Receptors (CLR) Rig Like Receptors (RLR) Mannose Receptors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Nod-like receptors except-", "options": [{"label": "A", "text": "Nod-like receptors are located in the nucleus", "correct": true}, {"label": "B", "text": "It signals via Inflammasome", "correct": false}, {"label": "C", "text": "Gain of function mutation causes 'Periodic fever syndrome'", "correct": false}, {"label": "D", "text": "It can be associated with gout", "correct": false}], "correct_answer": "A. Nod-like receptors are located in the nucleus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nod-like receptors are located in the nucleus NOD-like receptors (NLRs) are cytosolic receptors named after the founding member NOD-2. They recognize a wide variety of substances, including products released from necrotic or damaged cells (e.g., uric acid and adenosine triphosphate [ATP]), loss of intracellular K+ ions, and some microbial products.</p>\n<p><strong>Highyeild:</strong></p><p>Pattern Recognition Receptors: Pattern Recognition Receptors (PRR) are located in all cellular compartments where microbes may be present : Plasma membrane receptors detect extracellular microbes Endosomal receptors detect ingested microbes Cytosolic receptors detect microbes in the cytoplasm. Types of pattern recognized: PAMP : Pathogen Associated Molecular Pattern: Present on Pathogens. DAMP : Damage Associated Molecular Pattern: Present on Necrotic cells/Damaged cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B It signals via Inflammasome. Several of the NLRs signal via a cytosolic multiprotein complex called the Inflammasome , which activates an enzyme (caspase-1) that cleaves a precursor form of the cytokine interleukin-1 (IL-1) to generate the biologically active form. Option: C Gain of function mutation causes 'Periodic fever syndrome'. Gain-of-function mutations in NLRs and related proteins, and loss-of-function mutations in regulators of the Inflammasome, result in periodic fever syndromes called autoinflammatory syndromes . Opti on: D. It can be associated with gout. Recognition of urate crystals by a class of NLRs underlies the inflammation associated with gout . These receptors are also capable of detecting lipids and cholesterol crystals that are deposited in abnormally large amounts in tissues, and the resulting inflammation appears to contribute to obesity-associated type 2 diabetes and atherosclerosis , respectively.</p>\n<p><strong>Extraedge:</strong></p><p>Examples of PRR: Toll-Like Receptors (TLR) Nod-Like Receptors (NLR) C-Lectin Receptors (CLR) Rig Like Receptors (RLR) Mannose Receptors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The adaptive immune system consists of lymphocytes and their products, including antibodies. Which of the given statements is false?", "options": [{"label": "A", "text": "Cell-mediated immunity protects intracellular organisms", "correct": false}, {"label": "B", "text": "Humoral immunity protects against extracellular organisms", "correct": false}, {"label": "C", "text": "B cells are produced in the bone marrow", "correct": false}, {"label": "D", "text": "T cells are produced in the thymus", "correct": true}], "correct_answer": "D. T cells are produced in the thymus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>T cells are produced in the thymus T cells are produced in bone marrow but get matured in the thymus while B cells are produced and matured in bone marrow .</p>\n<p><strong>Highyeild:</strong></p><p>Innate vs Adaptive immunity Innate immunity Adaptive immunity Non specific Specific to antigen Always active Active only on post exposure to antigen Lag phase absent Longer lag phase present Diversity of antigen is limited Response to various diverse antigen is seen Memory is absent Memory is present E.g. Nk cells, MALT, skin epithelium, dendritic cells, complement system B and T lymphocytes, and T lymphocytes, plasma cells, antibodies Examples of Innate immunity: Skin epithelium Mucosal barrier (GIT/ Respiratory) WBCs: Neutrophils, Eosinophils, Basophils, and Monocytes NK cells Pattern Recognition Receptors Complement system Examples of Adaptive immunity: B and T Lymphocytes Plasma cells Antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cell-mediated immunity protects intracellular organisms. Cell-mediated (or cellular) immunity , is responsible for defense against intracellular microbes and cancers . Option: B. Humoral immunity protects against extracellular organisms. Humoral immunity protects against extracellular microbes and their toxins . Option: C. B cells are produced in the bone marrow. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is true regarding the activation of lymphocytes on antigen exposure?", "options": [{"label": "A", "text": "T cells are never required for the activation of B cells", "correct": false}, {"label": "B", "text": "B cells help in the activation of T cells", "correct": false}, {"label": "C", "text": "There is T cell-independent activation of B cells", "correct": true}, {"label": "D", "text": "CD 40 ligand present on B cells bind with CD 40 of T cells", "correct": false}], "correct_answer": "C. There is T cell-independent activation of B cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>There is T cell-independent activation of B cells Many polysaccharide and lipid antigens cannot be recognized by T cells (because they cannot bind to MHC molecules) but have multiple identical antigenic determinants (epitopes) that can engage many antigen receptor molecules on each B cell and initiate the process of B-cell activation ; these responses are said to be T-independent .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. T cells are never required for the activation of B cells. Antibody responses to most protein antigens require T-cell help and are said to be T-dependent . In these responses, B cells that recognize protein antigens by their Ig receptors endocytose these antigens into vesicles, degrade them, and display peptides bound to class II MHC molecules for recognition by helper T cells . The helper T cells are activated and express CD40L and secrete cytokines , which work together to stimulate the B cells. Option: B. B cells help in the activation of T cells. Naïve T lymphocytes are activated by antigens and costimulators in peripheral lymphoid organs and proliferate and differentiate into effector cells that migrate to any site where microbial antigens are present. T-cell activation does not require B cells. Optio n: D. CD 40 ligand present on B cells binds with CD 40 of T cells. CD40 is present in B cells and its ligand is present in the T cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Class switching is stimulated by-", "options": [{"label": "A", "text": "CD 40 of B cell", "correct": false}, {"label": "B", "text": "CD 40 L of T cell", "correct": true}, {"label": "C", "text": "CD 40 L of B cell", "correct": false}, {"label": "D", "text": "CD 40 of T cell", "correct": false}], "correct_answer": "B. CD 40 L of T cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD 40 L of T cell Protein antigens, by CD40L - and cytokine-mediated helper T-cell actions , induce the production of antibodies of different classes , or isotypes (IgG, IgA, IgE) , a process called Isotype/ Class switching . Helper T cells also stimulate the production of antibodies with high affinities for the antigen. This process, called Affinity maturation , improves the quality of the humoral immune response.</p>\n<p><strong>Highyeild:</strong></p><p>Antigen Presenting Cells: Cells that identify, process, and present Ag to T cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CD 40 of the B cell. Incorrect . Option: C. CD 40 L of the B cell. Incorrect . Option: D. CD 40 of T cell. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>If Class switching is defective , there is an increase in the production of IgM .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Epstein barr virus enters B lymphocytes via-", "options": [{"label": "A", "text": "CD21", "correct": true}, {"label": "B", "text": "CD40", "correct": false}, {"label": "C", "text": "CD79 a", "correct": false}, {"label": "D", "text": "CD79 b", "correct": false}], "correct_answer": "A. CD21", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD21 EBV enters B lymphocytes via CD21 . Type 2 complement receptor (CR2, or CD21) , which recognizes complement products generated during innate immune responses to microbes , and CD40, which receives signals from helper T cells. CR2 or CD21 is also used by the Epstein-Barr virus (EBV) as a receptor to enter and infect B cells .</p>\n<p><strong>Highyeild:</strong></p><p>Receptors for different microbes: EBV - CD 21CD40 HIV - gp 41 Parvovirus B 19 - P blood group Ag Paramyxo and Orthomyxovius - Mucoprotein receptor in Nasopharynx Rabies - Nicotinic Ach receptor</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. CD40. Protein antigens, by CD40L- and cytokine-mediated helper T-cell actions, induce the production of antibodies of different classes, or isotypes (IgG, IgA, IgE), a process called isotype switching . Option: C. CD79 a. CD79a and CD79b are Ig alpha and Ig beta. Similar to the CD3 and ζ proteins of the TCR complex, Igα (CD79a) and Igβ (CD79b) are essential for signal transduction in response to antigen recognition . Option: D. CD79 b. CD79a and CD79b are Ig alpha and Ig beta. Similar to the CD3 and ζ proteins of the TCR complex, Igα (CD79a) and Igβ (CD79b) are essential for signal transduction in response to antigen recognition .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Costimulatory molecules of T cells are-", "options": [{"label": "A", "text": "CD80", "correct": false}, {"label": "B", "text": "CD86", "correct": false}, {"label": "C", "text": "CD28", "correct": true}, {"label": "D", "text": "Both A and B", "correct": false}], "correct_answer": "C. CD28", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD28</p>\n<p><strong>Highyeild:</strong></p><p>During the innate response , the microbe or adjuvant activates antigen-presenting cells to express molecules called costimulators and to secrete cytokines that stimulate the proliferation and differentiation of T lymphocytes . The principal costimulators for T cells are the B7 proteins (CD80 and CD86) that are expressed on antigen-presenting cells and are recognized by the CD28 receptor on naïve T cells . Thus, antigen (“ signal 1 ”) and costimulatory molecules produced during innate immune responses to microbes (“ signal 2 ”) function cooperatively to activate antigen-specific lymphocytes. The requirement for microbe-triggered signal 2 ensures that the adaptive immune response is induced by microbes and not by harmless substances . In immune responses to tumors and transplants, “signal 2” may be provided by substances released from necrotic cells (the “damage-associated molecular patterns”). <</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CD 80. CD80 and CD86 are expressed on antigen-presenting cells and are recognized by the CD28 receptor on naïve T cells . Option: B. CD 86. CD80 and CD86 are expressed on antigen-presenting cells and are recognized by the CD28 receptor on naïve T cells. Option: Both A and B. The principal costimulators for T cells are the B7 proteins ( CD80 and CD86) that are expressed on antigen-presenting cells and are recognized by the CD28 receptor on naïve T cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the T lymphocytes helps in preventing autoimmunity?", "options": [{"label": "A", "text": "Helper T cell", "correct": false}, {"label": "B", "text": "Cytotoxic T cell", "correct": false}, {"label": "C", "text": "Regulatory T cell", "correct": true}, {"label": "D", "text": "Natural killer T cell", "correct": false}], "correct_answer": "C. Regulatory T cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Regulatory T cell Regulatory T lymphocytes limit immune responses and prevent reactions against self-antigens .</p>\n<p><strong>Highyeild:</strong></p><p>There are three major populations of T cells , which serve distinct functions: Helper T lymphocytes stimulate B lymphocytes to make antibodies and activate other leukocytes (e.g., phagocytes) to destroy microbes Cytotoxic (killer) T lymphocytes (CTLs) kill infected cells Regulatory T lymphocytes limit immune responses and prevent reactions against self-antigens . The best-defined regulatory T cells are CD4+ cells that express high levels of CD25 , the α chain of the IL-2 receptor , and FOXP3 , a transcription factor of the forkhead family. Both IL-2 and FOXP3 are required for the development and maintenance of functional CD4+ regulatory T cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Helper T cell. Helper T lymphocytes stimulate B lymphocytes to make antibodies and activate other leukocytes (e.g., phagocytes) to destroy microbes. Option: B. Cytotoxic T cell. Cytotoxic (killer) T lymphocytes (CTLs) kill infected cells . Option: D. Natural killer T cell. The function of NK cells is to r ecognize and destroy severely stressed or abnormal cells , such as virus-infected cells and tumor cells .</p>\n<p><strong>Extraedge:</strong></p><p>Mutations in FOXP3 result in severe autoimmunity in humans . Regulatory T cells prevent immune responses not only against self-antigens but also against the fetus and commensal microbes .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following molecules are expressed by regulatory T cells?", "options": [{"label": "A", "text": "CD8", "correct": false}, {"label": "B", "text": "FOXP3", "correct": true}, {"label": "C", "text": "CD21", "correct": false}, {"label": "D", "text": "CD40", "correct": false}], "correct_answer": "B. FOXP3", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FOXP3 Regulatory T lymphocytes express CD4, CD25 , and FOXP3 . Regulatory T lymphocytes limit immune responses and prevent reactions against self-antigens .</p>\n<p><strong>Highyeild:</strong></p><p>There are three major populations of T cells , which serve distinct functions: Helper T lymphocytes stimulate B lymphocytes to make antibodies and activate other leukocytes (e.g., phagocytes) to destroy microbes Cytotoxic (killer) T lymphocytes (CTLs) kill infected cells Regulatory T lymphocytes limit immune responses and prevent reactions against self-antigens . The best-defined regulatory T cells are CD4+ cells that express high levels of CD25 , the α chain of the IL-2 receptor , and FOXP3 , a transcription factor of the forkhead family. Both IL-2 and FOXP3 are required for the development and maintenance of functional CD4+ regulatory T cells . Mutations in FOXP3 result in severe autoimmunity in humans . Regulatory T cells prevent immune responses not only against self-antigens but also against the fetus and commensal microbes . Mechanisms of immunologic tolerance to self antigens. The principal mechanisms of central and peripheral self-tolerance in T and B cells are illustrated. APC, Antigen-presenting cell.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. CD8. Expressed by Cytotoxic T cells . Option: C. CD21. EBV enters B lymphocytes via CD21 . Option: D. CD40. Protein antigens, by CD40L- and cytokine-mediated helper T-cell actions, induce the production of antibodies of different classes, or isotypes (IgG, IgA, IgE), a process called isotype switching . .</p>\n<p><strong>Table:</strong></p><p>Receptors for different microbes: EBV - CD 21CD40 HIV - gp 41 Parvovirus B 19 - P blood group Ag Paramyxo and Orthomyxovius - Mucoprotein\n receptor in Nasopharynx Rabies - Nicotinic Ach receptor</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the lymphocytes show the phenomenon of Lymphocyte recirculation?", "options": [{"label": "A", "text": "B lymphocytes", "correct": false}, {"label": "B", "text": "T lymphocytes", "correct": true}, {"label": "C", "text": "Plasma cells", "correct": false}, {"label": "D", "text": "Both B and T lymphocytes", "correct": false}], "correct_answer": "B. T lymphocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>T lymphocytes Lymphocytes constantly recirculate between tissues and home to particular sites ; naïve lymphocytes traverse the secondary lymphoid organs where immune responses are initiated , and effector lymphocytes migrate to sites of infection and inflammation. This process of lymphocyte recirculation is most important for T cells because naïve T cells have to circulate through the secondary lymphoid organs where antigens are concentrated and effector T cells have to migrate to sites of infection to eliminate microbes .</p>\n<p><strong>Highyeild:</strong></p><p>Antigen Presenting Cells: Cells that identify, process, and present Ag to T cells</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. B lymphocytes. Remain in lymphoid organs and the bone marrow . Option: C. Plasma cell. Plasma cells remain in lymphoid organs and the bone marrow and do not need to traffic to sites of infection because they secrete antibodies that are carried through the blood to distant tissues . Option: D. Both B and T lymphocytes. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "On exposure to an antigen, which mechanism leads to the activation of T cells", "options": [{"label": "A", "text": "Dependent on B lymphocytes", "correct": false}, {"label": "B", "text": "Dependent on Antigen-presenting cells", "correct": true}, {"label": "C", "text": "Antigen directly stimulates T lymphocytes", "correct": false}, {"label": "D", "text": "Any of the above", "correct": false}], "correct_answer": "B. Dependent on Antigen-presenting cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dependent on Antigen-presenting cells Antigen-presenting cells (APCs) capture microbes and other antigens , transport them to secondary lymphoid organs , and display them for recognition by lymphocytes . The most efficient APCs are dendritic cells (DCs) , which are present in epithelia and most other tissues. Integrins are adhesion molecules that promote the attachment of T-cells to APCs . Signals: from APC to T cells MHC presenting Ag to TCR CD 80/86 activating CD 28 Specific cytokines from APC to T cells</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Dependent on B lymphocytes. B lymphocyte stimulation is dependent on T lymphocytes when there is a protein antigen . Option: C. Dependent on Antigen-presenting cells. The antigen cannot directly stimulate T lymphocytes . They need to be presented by APCs to T lymphocytes. Option: D. Any of the above. Incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 31 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Loss of contractibility of myocyte occurs after the ischemic duration of-", "options": [{"label": "A", "text": "2 min", "correct": true}, {"label": "B", "text": "40 min", "correct": false}, {"label": "C", "text": "10 min", "correct": false}, {"label": "D", "text": "> 1-hour", "correct": false}], "correct_answer": "A. 2 min", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>2 min Loss of contractility: < 2 min</p>\n<p><strong>Highyeild:</strong></p><p>Approximate Time of Onset of Key Events in Ischemic Cardiac Myocytes Feature Time Onset of ATP depletion Seconds Loss of contractility <2 minutes ATP reduced to 50% of normal to 10% of normal 10 minutes 40 minutes Irreversible cell injury 20-40 minutes Microvascular injury >I hour ATP, Adenosine triphosphate.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B.. 40 min. ATP is reduced to 10% of normal and irreversible cell injury occurs . Option: C:. 10 min. ATP is reduced to 50% of normal . Option: D. >1 hour. Microvascular injury takes place .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In an ischemic event, irreversible injury of myocyte occurs, first in which zone:", "options": [{"label": "A", "text": "Epicardium", "correct": false}, {"label": "B", "text": "Subendocardium", "correct": true}, {"label": "C", "text": "Myocardium", "correct": false}, {"label": "D", "text": "Trans mural thickness", "correct": false}], "correct_answer": "B. Subendocardium", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Subendocardium Irreversible injury of ischemic myocytes first occurs in the subendocardial zone . This region is especially susceptible to ischemia because: It is the last area to receive blood delivered by the epicardial vessels . Because it is exposed to relatively high intramural pressures , which act to impede the inflow of blood . Endocardium is perfused by being directly in contact with blood present in the ventricles , making the subendocardium more susceptible than the endocardium.</p>\n<p><strong>Highyeild:</strong></p><p>Transmural infarct: Involves the entire thickness of the wall , and occurs due to complete occlusion of the epicardial vessel . These are usually associated with chronic coronary atherosclerosis, acute plaque change, and superimposed thrombosis . Subendocardial infarct: Involves portion just beneath the endocardium , occurs due to partial occlusion of the epicardial vessel, hypotension/shock . In the subendocardial infarcts that occur due to global hypotension, myocardial damage is often circumferential , rather than being limited to the distribution of a single major coronary artery. Multifocal microinfarct: Involves smaller intramural vessels , and occurs due to microemboli, vasculitis, vasospasm , increase in endogenous catecholamines ( epinephrine ) or drugs ( cocaine ). Elevated levels of catecholamines also increase heart rate and myocardial contractility, exacerbating ischemia caused by the vasospasm, the outcome of such vasospasm can be sudden cardiac death.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Epicardium. Incorrect . Option: C. Myocardium. Incorrect . Option: D. Trans mural thickness. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The area of Myocyte necrosis can be identified by immersion of tissue flies in a solution of triphenyl tetrazolium chloride which provides a color of:", "options": [{"label": "A", "text": "Brick red color", "correct": false}, {"label": "B", "text": "Unstained", "correct": true}, {"label": "C", "text": "White color", "correct": false}, {"label": "D", "text": "Black color", "correct": false}], "correct_answer": "B. Unstained", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Unstained Pale unstained zone represents the infarcted myocardium .</p>\n<p><strong>Highyeild:</strong></p><p>In autopsy when death is due to myocardial infarction , it is possible to highlight the area of necrosis by immersion of tissue slices in a solution of Triphenyl tetrazolium chloride . Acute myocardial infarct, predominantly of the posterolateral left ventricle, demonstrated histochemically by a lack of staining by triphenyltetrazolium chloride in areas of necrosis (arrow). The staining defect is due to the lactate dehydrogenase leakage that follows cell death. Note the myocardial hemorrhage at one edge of the infarct that was associated with cardiac rupture, and the anterior scar (arrowhead), indicative of an old infarct. The specimen is oriented with the posterior wall at the top.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Brick red color. Incorrect , represents the viable myocardium . Option: C. White color. Incorrect , represents the scar tissue, indicative of an old infarct Option: D. Black color. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Triphenyl tetrazolium chloride Represents Reason Brick red Viable myocardium Preserved Lactate dehydrogenase activity Pale unstained zone (marked with an arrow in the image) Infarcted myocardium Leakage of lactate dehydrogenase from damaged membranes of dead cells White area (marked with an arrowhead in the image) Scar tissue, indicative of an old infarct Fibrous scar</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "At what duration of myocardial infarction does light microscopy demonstrate myocyte necrosis, hypereosinophilia, contraction band necrosis, and early neutrophil infiltrate:", "options": [{"label": "A", "text": "4-6 hr", "correct": false}, {"label": "B", "text": "12-24hr", "correct": true}, {"label": "C", "text": "1-3 days", "correct": false}, {"label": "D", "text": "3-7 days", "correct": false}], "correct_answer": "B. 12-24hr", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>12-24hr At 12-24 hr , light microscopy demonstrates Ongoing coagulative necrosis, pyknosis of nuclei; myocyte hypereosinophilia; marginal contraction band necrosis; early neutrophilic infiltrate .</p>\n<p><strong>Highyeild:</strong></p><p>Evolution of Morphological Changes in Myocardial infarction: Time Gross Features Light Microscope Electron Microscope Reversible Injury 0-%½ hour None None Relaxation of myofibrils; glycogen loss; mitochondrial swelling Irreversible Injury ½-4 hours None Usually none; variable waviness of fibers at border Sarcolemmal disruption; mitochondrial amorphous densities 4-12 hours Dark mottling (occasional) Early coagulative necrosis; edema; hemorrhage 12-24 hours Dark mottling Ongoing coagulative necrosis: pyknosis of nuclei; myocyte hypereosinophilia; marginal contraction band necrosis; early neutrophilic infiltrate 1-3 days Mottling with yellow-tan infarct center Coagulative necrosis, with loss of nuclei and striations; brisk interstitial infiltrate of neutrophils 3-7 days Hyperemic border; central yellow-tan softening Beginning disintegration of dead myofibers, with dying neutrophils; early phagocytosis of dead cells by macrophages at infarct border 7-10 days Maximally yellow-tan and soft, with depressed red-tan margins Well-developed phagocytosis of dead cells; granulation tissue at margins 10-14 days Red-gray depressed infarct borders Well-established granulation tissue with new blood vessels and collagen deposition 2-8 weeks Gray-white scar, progressive from border toward core of infarct Increased collagen deposition, with decreased cellularity >2 months Scarring complete Dense collagenous scar</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. 4-6 hr. Incorrect , light microscopy shows Early coagulative necrosis; edema; hemorrhage . Option: C. 1-3 days. Incorrect , light microscopy shows Coagulative necrosis, with loss of nuclei and striations; brisk interstitial infiltrate of neutrophils . Option: D. 3-7 days. Incorrect , light microscopy shows the Beginning disintegration of dead myofibers, with dying neutrophils; early phagocytosis of dead cells by macrophages at the infarct border .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "At what duration of myocardial infarction light microscopy demonstrate new blood vessel and collagen depositions:", "options": [{"label": "A", "text": "7-10 days", "correct": false}, {"label": "B", "text": "10-14 days", "correct": true}, {"label": "C", "text": "2-3 weeks", "correct": false}, {"label": "D", "text": "> 2 months", "correct": false}], "correct_answer": "B. 10-14 days", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>10-14 days At 10-14 days, light microscopy demonstrates well-established granulation tissue with new blood vessels and collagen deposition .</p>\n<p><strong>Highyeild:</strong></p><p>Evolution of Morphological Changes in Myocardial infarction: Time Gross Features Light Microscope Electron Microscope Reversible Injury 0-%½ hour None None Relaxation of myofibrils; glycogen loss; mitochondrial swelling Irreversible Injury ½-4 hours None Usually none; variable waviness of fibers at border Sarcolemmal disruption; mitochondrial amorphous densities 4-12 hours Dark mottling (occasional) Early coagulative necrosis; edema; hemorrhage 12-24 hours Dark mottling Ongoing coagulative necrosis: pyknosis of nuclei; myocyte hypereosinophilia; marginal contraction band necrosis; early neutrophilic infiltrate 1-3 days Mottling with yellow-tan infarct center Coagulative necrosis, with loss of nuclei and striations; brisk interstitial infiltrate of neutrophils 3-7 days Hyperemic border; central yellow-tan softening Beginning disintegration of dead myofibers, with dying neutrophils; early phagocytosis of dead cells by macrophages at infarct border 7-10 days Maximally yellow-tan and soft, with depressed red-tan margins Well-developed phagocytosis of dead cells; granulation tissue at margins 10-14 days Red-gray depressed infarct borders Well-established granulation tissue with new blood vessels and collagen deposition 2-8 weeks Gray-white scar, progressive from border toward core of infarct Increased collagen deposition, with decreased cellularity >2 months Scarring complete Dense collagenous scar</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. 7-10 days. Incorrect , light microscopy shows Well-developed phagocytosis of dead cells; granulation tissue at margins . Option: C. 2-3 weeks. Incorrect , light microscopy shows Increased collagen deposition, with decreased cellularity . Option: D. > 2 months. Incorrect , light microscopy shows a Dense collagenous scar .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Earliest light microscopic change in myocardial infarction is:", "options": [{"label": "A", "text": "Waviness of fiber", "correct": true}, {"label": "B", "text": "Neutrophilic infiltration", "correct": false}, {"label": "C", "text": "Coagulative necrosis", "correct": false}, {"label": "D", "text": "Collagen deposition", "correct": false}], "correct_answer": "A. Waviness of fiber", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Waviness of fiber Earliest light microscopic change in myocardial infarction is the Waviness of fiber Microscopic features of myocardial infarction and its repair. (A) One-day-old infarct showing coagulative necrosis and wavy fibers (elongated and narrow, as compared with adjacent standard fibers at right).</p>\n<p><strong>Highyeild:</strong></p><p>Evolution of Morphological Changes in Myocardial infarction: Time Gross Features Light Microscope Electron Microscope Reversible Injury 0-%½ hour None None Relaxation of myofibrils; glycogen loss; mitochondrial swelling Irreversible Injury ½-4 hours None Usually none; variable waviness of fibers at border Sarcolemmal disruption; mitochondrial amorphous densities 4-12 hours Dark mottling (occasional) Early coagulative necrosis; edema; hemorrhage 12-24 hours Dark mottling Ongoing coagulative necrosis: pyknosis of nuclei; myocyte hypereosinophilia; marginal contraction band necrosis; early neutrophilic infiltrate 1-3 days Mottling with yellow-tan infarct center Coagulative necrosis, with loss of nuclei and striations; brisk interstitial infiltrate of neutrophils 3-7 days Hyperemic border; central yellow-tan softening Beginning disintegration of dead myofibers, with dying neutrophils; early phagocytosis of dead cells by macrophages at infarct border 7-10 days Maximally yellow-tan and soft, with depressed red-tan margins Well-developed phagocytosis of dead cells; granulation tissue at margins 10-14 days Red-gray depressed infarct borders Well-established granulation tissue with new blood vessels and collagen deposition 2-8 weeks Gray-white scar, progressive from border toward core of infarct Increased collagen deposition, with decreased cellularity >2 months Scarring complete Dense collagenous scar</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Neutrophilic infiltration. Incorrect , starts at 12-24 hours and is seen till 1-3 days. Option: C. Coagulative necrosis. Incorrect , begins at 4-12 hours and is seen till 1-3 days. Option: D. Collagen deposition. Incorrect , begins at 10-14 days and is seen after 2 months.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Sublethal ischemic change which reflects the intracellular accumulation of salt and water in sarcoplasmic reticulum within known as:", "options": [{"label": "A", "text": "Myocytolysis", "correct": true}, {"label": "B", "text": "Wavy fiber", "correct": false}, {"label": "C", "text": "Myocytolitis", "correct": false}, {"label": "D", "text": "Granulation tissue", "correct": false}], "correct_answer": "A. Myocytolysis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myocytolysis Sublethal ischemic change may be seen in the margins of infarcts: this so-called Myocyte Vacuolization or Myocytolysis reflects intracellular accumulations of salt and water within the sarcoplasmic reticulum , and marks myocytes that are viable but poorly contractile.</p>\n<p><strong>Highyeild:</strong></p><p>Evolution of Morphological Changes in Myocardial infarction: Time Gross Features Light Microscope Electron Microscope Reversible Injury 0-%½ hour None None Relaxation of myofibrils; glycogen loss; mitochondrial swelling Irreversible Injury ½-4 hours None Usually none; variable waviness of fibers at border Sarcolemmal disruption; mitochondrial amorphous densities 4-12 hours Dark mottling (occasional) Early coagulative necrosis; edema; hemorrhage 12-24 hours Dark mottling Ongoing coagulative necrosis: pyknosis of nuclei; myocyte hypereosinophilia; marginal contraction band necrosis; early neutrophilic infiltrate 1-3 days Mottling with yellow-tan infarct center Coagulative necrosis, with loss of nuclei and striations; brisk interstitial infiltrate of neutrophils 3-7 days Hyperemic border; central yellow-tan softening Beginning disintegration of dead myofibers, with dying neutrophils; early phagocytosis of dead cells by macrophages at infarct border 7-10 days Maximally yellow-tan and soft, with depressed red-tan margins Well-developed phagocytosis of dead cells; granulation tissue at margins 10-14 days Red-gray depressed infarct borders Well-established granulation tissue with new blood vessels and collagen deposition 2-8 weeks Gray-white scar, progressive from border toward core of infarct Increased collagen deposition, with decreased cellularity >2 months Scarring complete Dense collagenous scar</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options B , C and D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In myocardial reperfusion injury, the maximum effect is caused by:", "options": [{"label": "A", "text": "Neutrophils", "correct": false}, {"label": "B", "text": "Monocytes", "correct": false}, {"label": "C", "text": "Free radicals", "correct": true}, {"label": "D", "text": "Eosinophils", "correct": false}], "correct_answer": "C. Free radicals", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Free radicals Reperfusion injury may be mediated by oxidative stress , calcium overload , and inflammatory cells recruited after tissue reperfusion.</p>\n<p><strong>Highyeild:</strong></p><p>Reperfusion Injury: The therapeutic goal in acute MI is to salvage the maximal amount of ischemic myocardium ; which is accomplished by restoration of tissue perfusion as quickly as possible , by thrombolysis using Tissue Plasminogen Activator ( TPA ), Angioplasty or Coronary artery Bypass Graft ( CABG ). But sometimes, late restoration of blood into the ischemic myocardium can cause arrhythmia and more damage called Reperfusion Injury . Factors that contribute to Reperfusion injury include Mitochondrial dysfunction Myocyte hyper contracture Free radicals Leukocyte aggregation Platelet and complement activation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A , B and D are incorrect</p>\n<p><strong>Extraedge:</strong></p><p>Microscopically, irreversibly damaged myocytes after reperfusion develops c ontraction band necrosis ; in this pathologic process, intense eosinophilic bands of hypercontracted sarcomeres are created by an influx of calcium across plasma membranes which heightens actin-myosin interactions . In the absence of ATP, the sarcomeres cannot relax and get stuck in an agonal tetanic state . Thus, although reperfusion can salvage reversibly injured cells , it also alters the morphology of irreversibly wounded cells .</p>\n<p><strong>Table:</strong></p><p>Reperfusion injury: Factors that contribute to Reperfusion injury include 1. Mitochondrial dysfunction 2. Myocyte hyper contracture 3. Free radicals 4. Leukocyte aggregation 5. Platelet and complement activation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Stunned myocardium term is related to:", "options": [{"label": "A", "text": "Biochemical abnormalities", "correct": true}, {"label": "B", "text": "Pericarditis", "correct": false}, {"label": "C", "text": "Myxoma", "correct": false}, {"label": "D", "text": "Ventricular aneurysm", "correct": false}], "correct_answer": "A. Biochemical abnormalities", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Biochemical abnormalities Biochemical abnormalities (and their functional consequences) may also persist for days to weeks in reperfused myocytes. Such changes are thought to underlie a phenomenon referred to as stunned myocardium , a state of prolonged cardiac failure induced by short-term ischemia that usually recovers after several days .</p>\n<p><strong>Highyeild:</strong></p><p>Reperfusion Injury: The therapeutic goal in acute MI is to salvage the maximal amount of ischemic myocardium ; which is accomplished by restoration of tissue perfusion as quickly as possible , by thrombolysis using Tissue Plasminogen Activator ( TPA ), Angioplasty or Coronary artery Bypass Graft ( CABG ). But sometimes, late restoration of blood into the ischemic myocardium can cause arrhythmia and more damage called Reperfusion Injury . Factors that contribute to Reperfusion injury include Mitochondrial dysfunction Myocyte hyper contracture Free radicals Leukocyte aggregation Platelet and complement activation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options B , C and D are incorrect</p>\n<p><strong>Extraedge:</strong></p><p>Microscopically, irreversibly damaged myocytes after reperfusion develops c ontraction band necrosis ; in this pathologic process, intense eosinophilic bands of hypercontracted sarcomeres are created by an influx of calcium across plasma membranes which heightens actin-myosin interactions . In the absence of ATP, the sarcomeres cannot relax and get stuck in an agonal tetanic state . Thus, although reperfusion can salvage reversibly injured cells , it also alters the morphology of irreversibly wounded cells .</p>\n<p><strong>Table:</strong></p><p>Reperfusion injury: Factors that\ncontribute to Reperfusion injury include 1. Mitochondrial dysfunction 2. Myocyte hyper\ncontracture 3. Free radicals 4. Leukocyte aggregation 5. Platelet and complement\nactivation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "At what duration Troponin T & I begin to rise in the blood vessel after myocardial infarction:", "options": [{"label": "A", "text": "3-12 hr", "correct": true}, {"label": "B", "text": "12-24 hr", "correct": false}, {"label": "C", "text": "1-3 days", "correct": false}, {"label": "D", "text": "3-5 days", "correct": false}], "correct_answer": "A. 3-12 hr", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>3-12 hr Troponins I and T are normally not detectable in circulation . Following an MI, levels of both begin to rise at 2-4 hours , thus we go for the closest Option: as the answer i.e. 3-12 hrs .</p>\n<p><strong>Highyeild:</strong></p><p>Serial Troponin T and I are the most sensitive biomarkers for diagnosis of recent Myocardial infarction , they are proteins that normally regulate calcium-mediated contraction of cardiac muscle. The diagnosis of myocardial injury is established when blood levels of troponin are elevated above threshold levels. Cardiac troponins begin to rise in 2-4 hours and peak at 24-48 hours after an acute infarct. Troponins are an indicator of myocyte death and thus can be elevated even in Myocarditis and myocardial trauma . Troponins can also leak in other conditions such as Congestive heart failure, Pulmonary embolism, Renal failure, and sepsis . Serial measurements are thus helpful to differentiate such conditions from Myocardial Infarction (MI) as a serial rise in troponins is seen with MI .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options B , C and D are incorrect</p>\n<p><strong>Extraedge:</strong></p><p>CK-MB, Troponin T, LDH 1 are all elevated in MI but the best biomarkers for MI are serial measurements of Troponin T and I.</p>\n<p><strong>Table:</strong></p><p>Cardiac markers to rise after IHD: · 1-2 hrs: Myoglobin · 2-4 hrs: CK · 4-8 hrs: Troponin (persists up to 14 days) 6-12 hrs: CK-MB (persists up to 48 hrs</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Earliest change in systemic hypertensive heart disease:", "options": [{"label": "A", "text": "Nuclear enlargement", "correct": false}, {"label": "B", "text": "Interstitial fibrosis", "correct": false}, {"label": "C", "text": "Increase in transverse the diameter of myocyte", "correct": true}, {"label": "D", "text": "Cellular enlargement", "correct": false}], "correct_answer": "C. Increase in transverse the diameter of myocyte", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increase in transverse the diameter of myocyte Microscopically, the earliest change of systemic Hypertensive Heart Disease (HHD) is an increase in the transverse diameter of myocytes , which may be difficult to appreciate on routine microscopy.</p>\n<p><strong>Highyeild:</strong></p><p>Hypertensive heart disease (HHD): Hypertensive heart disease (HHD) is a consequence of the increased demands placed on the heart by hypertension , causing pressure overload and ventricular hypertrophy . Hypertrophy of the heart is an adaptive response to the pressure overload of chronic hypertension. The minimal pathologic criteria for the diagnosis of systemic HHD are the following: Left ventricular hypertrophy (usually concentric) in the absence of other cardiovascular pathology A clinical history or pathologic evidence of hypertension in other organs (e.g., kidney). Hypertension induces left ventricular pressure overload hypertrophy , initially without ventricular dilation . As a result, the left ventricular wall thickening increases the weight of the heart disproportionately to the increase in overall cardiac size . Over time, the increased thickness of the left ventricular wall, associated with increased interstitial connective tissue , imparts a stiffness that impairs diastolic filling , often leading to left atrial enlargement . Hypertensive heart disease, systemic and pulmonary. (A) Systemic (left-sided) hypertensive heart disease. There is marked concentric thickening of the left ventricular wall causing reduction in lumen size. The left ventricle and left atrium (asterisk) are on the right in this apical four-chamber view of the heart. A pacemaker is present in the right ventricle (arrow). (B) Pulmonary (right-sided) hypertensive heart disease (cor pulmonale). The right ventricle is markedly dilated and has a thickened free wall and hypertrophied trabeculae (apical four-chamber view of heart, right ventricle on left). The shape of the left ventricle (to the right) has been distorted by the enlarged right ventricle. Microscopically, the earliest change of systemic Hypertensive Heart Disease (HHD) is an increase in the transverse diameter of myocytes , which may be difficult to appreciate on routine microscopy. At a more advanced stage , variable degrees of cellular and nuclear enlargement become apparent , often accompanied by perivascular and interstitial fibrosis . Effective control of hypertension can prevent cardiac hypertrophy and can even lead to its regression ; with normalization of blood pressure, the associated risks of HHD are diminished .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Nuclear enlargement. Incorrect , seen in the advanced stage . Option: B. Interstitial fibrosis. Incorrect , seen in the advanced stage . Option: D. Cellular enlargement. Incorrect , seen in the advanced stage .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 21 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding lepromatous leprosy except:", "options": [{"label": "A", "text": "It shows weak TH 1 response", "correct": false}, {"label": "B", "text": "Bacteria involve Schwann cell, ends and perineural area", "correct": false}, {"label": "C", "text": "Protective antibody generation is commonly seen", "correct": true}, {"label": "D", "text": "It is multibacillary", "correct": false}], "correct_answer": "C. Protective antibody generation is commonly seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Protective antibody generation is commonly seen Lepromatous leprosy is associated with a weak TH1 response and, in some cases, a relative increase in the TH2 response. Occasionally, in the lepromatous form, antibodies are produced against M. leprae antigens . Paradoxically, these antibodies are usually not protective , but they may form immune complexes with free antigens that can lead to erythema nodosum , vasculitis , and glomerulonephritis . Lepromatous Leprosy is referred to as Multibacillary leprosy . lepromatous leprosy, widespread invasion of the mycobacteria into Schwann cells and into endoneurial and perineural macrophages damages the peripheral nervous system .</p>\n<p><strong>Highyeild:</strong></p><p>Ridley Classification Tuberculoid Leprosy (TT) Borderline Tuberculoid (BT) Borderline Leprosy (BB) Borderline Leprosy (BL) Lepromatous Leprosy (LL)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It shows a weak TH 1 response. True . Option: B. Bacteria involve Schwann cells, ends, and perineural area. True . Option: D. It is multibacillary. True .</p>\n<p><strong>Extraedge:</strong></p><p>Observation or test Type of leprosy TT BT BB BL LL Number of lesions Single usually Single or few Several Many Very many Size of lesions Variable Variable Variable Variable Small Surface of lesions Very dry, sometimes scaly Dry Slightly shiny Shiny Shiny Sensation in lesions (not face) Absent Moderately or mark- edly diminished Slightly or moderately diminished Slightly diminished Not affected or minimally affected Hair growth in lesions Absent Markedly diminished Moderately dimin- ished Slightly diminished Not affected AFB in lesions Nil Nil or scanty Moderate numbers Many Very many (plus globi) AFB in nasal scraping or in nose blows Nil Nil Nil Usually nil Very many (plus globi) Lepromin test Strongly positive (+++) Weakly positive (+ or ++) Negative Negative Negative</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Skin biopsy from the hypothetic patch is shown below based on the characteristic histological findings that identify the disease:", "options": [{"label": "A", "text": "Lichen planus", "correct": false}, {"label": "B", "text": "Psoriasis", "correct": false}, {"label": "C", "text": "Leprosy", "correct": true}, {"label": "D", "text": "Leukocytoclastic vasculitis", "correct": false}], "correct_answer": "C. Leprosy", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686826715147-QTDP067002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leprosy Neuronal involvement dominates tuberculoid leprosy . Nerves become enclosed within granulomatous inflammatory reactions and, if small (e.g. the peripheral twigs), are destroyed. Nerve degeneration causes skin anesthesias and skin and muscle atrophy that render the person liable to the trauma of the affected parts, leading to the development of chronic skin ulcers . Contractures paralyze, and autoamputation of fingers or toes may ensue. Facial nerve involvement can lead to paralysis of the eyelids, with keratitis and corneal ulcerations . On microscopic examination , all sites of involvement have granulomatous lesions closely resembling those found in tuberculosis. Because of the strong host defense, bacilli are almost never found, hence the name paucibacillary leprosy . The presence of granulomas and the absence of bacteria reflect strong T-cell immunity.</p>\n<p><strong>Highyeild:</strong></p><p>Superficial branch of the radial nerve is used for nerve biopsy in neuritic leprosy . Usually, sensory nerves are preferred for biopsy over mixed or motor nerves. Common nerves used for biopsy: Superficial branch of the radial nerve. Ulnar cutaneous nerve Sural nerve</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Lichen planus. Microscopy shows Hyperkeratosis, Max Joseph space, Saw toothing of Rete ridges, and band-like lymphocytic infiltrate. Option: B. Psoriasis. Microscopy shows Hyperkeratosis, Parakeratosis, Munro’s microabscess, Spongiform pustule of Kogoj, and dilated blood vessels in the dermis. Option: D. Leucocytoclastic vasculitis. Microscopy shows busy dermis with a superficial and mid-perivascular inflammatory pattern. There is a population of predominantly neutrophils in a perivascular and interstitial pattern in addition to those undergoing extravasation from the vessels. Leukocytoclastis (neutrophil degeneration) forming nuclear dust is seen in addition to extravasated erythrocytes. Fibrinoid necrosis of the vessels is also seen.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A distinctive feature of Lyme disease when causing arthritis that is not seen in rheumatoid arthritis is:", "options": [{"label": "A", "text": "Villous hypertrophy", "correct": false}, {"label": "B", "text": "Synovial hyperplasia", "correct": false}, {"label": "C", "text": "Lymphoplasmacytic infiltrate", "correct": false}, {"label": "D", "text": "Arteritis", "correct": true}], "correct_answer": "D. Arteritis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Arteritis Lyme disease is a common arthropod-borne illness caused by spirochetes in the genus Borrelia ( burgdorferi ) that can be localized or disseminated with a tendency to cause persistent chronic arthritis . infected tissue. Lyme disease involves multiple organ systems and is divided into three stages: In early localized disease , spirochetes multiply and spread in the dermis at the site of a tick bite , causing an expanding area of redness, often with a pale center. This lesion, called erythema migrans , may be accompanied by fever and lymphadenopathy. In early disseminated disease , spirochetes spread hematogenously throughout the body and cause secondary skin lesions, lymphadenopathy, migratory joint and muscle pain, cardiac arrhythmias, and meningitis often associated with cranial nerve involvement. The third stage, late disseminated disease , manifests many months after the tick bite. B. burgdorferi usually causes chronic arthritis sometimes with severe damage to large joints . Less often, patients will have polyneuropathy and encephalitis that vary from mild to debilitating.</p>\n<p><strong>Highyeild:</strong></p><p>Lyme’s disease is transmitted by Ixodid tick/ Deer tick and results in Bull’s eye lesion</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Villous hypertrophy. Seen in both Lyme disease and Rheumatoid arthritis . Option: B. Synovial hyperplasia. Seen in both Lyme disease and Rheumatoid arthritis . Option: C. Lympho-plasmacytic infiltrate. Seen in both Lyme disease and Rheumatoid arthritis .</p>\n<p><strong>Extraedge:</strong></p><p>Skin lesions caused by B. burgdorferi are characterized by edema and a lymphocytic-plasma cell infiltrate . In early Lyme arthritis, the synovium resembles early rheumatoid arthritis, with villous hypertrophy, lining-cell hyperplasia, and abundant lymphocytes and plasma cells in the sub synovium . A distinctive feature of Lyme arthritis is arteritis , which produces onion-skin-like lesions resembling those seen in lupus . In late Lyme disease, there may be extensive erosion of the cartilage in large joints. In Lyme meningitis, the CSF is hypercellular due to a marked lymphoplasmacytic infiltrate, and it contains anti-spirochete IgGs.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pseudomembranous colitis is caused by", "options": [{"label": "A", "text": "Clostridium perfrigens", "correct": false}, {"label": "B", "text": "C.tetani", "correct": false}, {"label": "C", "text": "C.difficile", "correct": true}, {"label": "D", "text": "Cbotulinum", "correct": false}], "correct_answer": "C. C.difficile", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C.difficile difficile proliferates in the intestines when competition by normal commensal microbiota is reduced by antibiotic treatment . The bacteria release toxins and cause pseudomembranous colitis . difficile produces toxin A , an enterotoxin that stimulates chemokine production and thus attracts leukocytes, and toxin B , a cytotoxin that causes distinctive cytopathic effects in cultured cells. Both toxins are glucosyl transferases and are part of a pathogenicity island that is absent from the chromosomes of nonpathogenic strains of C. difficile. There has been significant success in the treatment of C. difficile with fecal transplantation , emphasizing the role of normal commensal microbiota in defense against pathogens.</p>\n<p><strong>Highyeild:</strong></p><p>Drugs causing Pseudomembranous colitis: MNEMONIC: TALC Tetracyclines Ampicillin and Amoxicillin Lincosamide (Clindamycin) Cephalosporins Drug of choice for Pseudomembranous colitis: Oral vancomycin Drug causing maximum relapse prevention: Fidaxomycin</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Clostridium perfins. Causes cellulitis and myonecrosis of traumatic and surgical wounds (gas gangrene) , uterine myonecrosis is often associated with illegal abortions. Option: B. C. tetani. Causes tetanus , proliferates in puncture wounds and in the umbilical stump of newborn infants, and releases a potent neurotoxin that causes increased muscle tone and generalized spasms of skeletal muscles ( lockjaw ). Option: D. C.botulinum. Causes botulism , grows in inadequately cooked foods, and releases a potent neurotoxin that blocks the synaptic release of acetylcholine and causes flaccid paralysis of respiratory and skeletal muscles .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A stellate abscess is seen in:", "options": [{"label": "A", "text": "Chlamydia", "correct": true}, {"label": "B", "text": "Tuberculosis", "correct": false}, {"label": "C", "text": "Clostridium", "correct": false}, {"label": "D", "text": "Syphilis", "correct": false}], "correct_answer": "A. Chlamydia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chlamydia The lesions of lymphogranuloma venereum (LGV) contain a mixed granulomatous and neutrophilic inflammatory response. Variable numbers of chlamydial inclusions are seen in the cytoplasm of epithelial cells or inflammatory cells. Regional lymphadenopathy is common, usually occurring within 30 days of infection. Lymph node involvement is characterized by a granulomatous inflammatory reaction associated with irregularly shaped foci of necrosis containing neutrophils ( stellate abscesses ). With time, the inflammatory reaction is dominated by nonspecific chronic inflammatory infiltrates and extensive fibrosis. The latter, in turn, may cause local lymphatic obstruction, lymphedema, and strictures . In active lesions, the diagnosis of lymphogranuloma venereum may be made by demonstration of the organism in biopsy sections or smears of exudate. In more chronic cases, the diagnosis rests with the demonstration of antibodies to the appropriate chlamydial serotypes in the patient’s serum.</p>\n<p><strong>Highyeild:</strong></p><p>STI kit used for LGV: Black kit .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Tuberculosis. Incorrect . Option: C. Clostridium. Incorrect . Option: D. Syphilis. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following disease shows characteristic Escher formation and lymphadenopathy at the site of chigger bite:", "options": [{"label": "A", "text": "Epidemic typhus", "correct": false}, {"label": "B", "text": "Rocky Mountain fever", "correct": false}, {"label": "C", "text": "Scrub typhus", "correct": true}, {"label": "D", "text": "Ehrlichosis", "correct": false}], "correct_answer": "C. Scrub typhus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Scrub typhus (caused by Orienta tsutsugamushi ) is transmitted by chiggers . It is endemic in areas of Asia, Australia, and some islands in the western Pacific and Indian Oceans. Fever, headache, myalgia, and cough are usual symptoms , sometimes accompanied by a characteristic eschar and associated lymphadenopathy from the chigger bite. The rash is usually transitory or might not appear.</p>\n<p><strong>Highyeild:</strong></p><p>Typhus group of fever: Disease Causative organism Transmitted by Epidemic Typhus R prowazakii Louse Endemic Typhus or Murine Typhus R typhi Flea Rocky Mountain Spotted Fever R rickettsia Hard Tick Scrub Typhus Orentia Tsutsugamushi Trombiculid Mite Q fever Coxiella Burnetta Air > Soft Tick Trench fever/ Quintaniac fever Bartonella Quintana Louse Rickettsial pox R Akari Mite Scabies Sarcoptes Scabies Itch Mite Indian Tick Typhus R conorii Hard Tick</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Epidemic typhus. Caused by Rickettsia prowazekii is transmitted from person to person by body lice . It is associated with wars and poverty, when individuals live in close contact with poor hygiene . Manifestations include a rash that is initially macular, progressing to a petechial, maculopapular rash on the entire body EXCEPT the face, palms, and soles . Option: B. Rocky Mountain fever. Caused by Rickettsia rickettsii is transmitted to humans by dog ticks . It begins as a nonspecific severe illness with fever, myalgias, and gastrointestinal distress, and then progresses to a widespread macular then petechial rash that can involve the palms and soles . Option: D. Ehrlichosis. Caused mainly by Ehrlichia chaffeensis) and anaplasmosis (Anaplasma phagocytophilum) is transmitted by the lone star tick and deer tick, respectively. These bacteria predominantly infect monocytes (E. chaffeensis) or neutrophils (A. phagocytophilum). Ehrlichiosis and anaplasmosis are characterized by abrupt onset of fever, headache, and malaise, and may progress to respiratory insufficiency, renal failure, and shock.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding the cervix except:", "options": [{"label": "A", "text": "Ectocervix lined by squamous epithelium", "correct": false}, {"label": "B", "text": "Endocervix lined by columnar epithelium", "correct": false}, {"label": "C", "text": "Position of the squamocolumnar junction is fixed", "correct": true}, {"label": "D", "text": "Transformation zone is susceptible to HPV infection", "correct": false}], "correct_answer": "C. Position of the squamocolumnar junction is fixed", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Position of the squamocolumnar junction is fixed The position of the squamocolumnar junction (the boundary between the squamous epithelium of the ectocervix and the columnar epithelium of the endocervix) is not fixed. It can vary in position and can move over time, especially in response to hormonal changes or with certain conditions such as pregnancy or inflammation.</p>\n<p><strong>Highyeild:</strong></p><p>Cervix: Anatomy and Histology It has 2 main parts: Ectocervix : Visible part of the cervix that protrudes into the vagina It is lined by stratified squamous epithelium. Can withstand friction and mechanical stress. Endocervix : Part of the cervix that extends into the cervical canal . It is lined by simple columnar epithelium. This type of epithelium produces mucus and plays a role in fertility and menstruation. Squamous-columnar junction : Boundary between the squamous epithelium of the ectocervix and the columnar epithelium of the endocervix. The transformation zone: Area of the cervix where the squamous epithelium transitions to the columnar epithelium. The unique epithelial environment of the cervix renders it highly susceptible to infections with HPV.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., D: All are true</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding cervical infection by HPV infection except", "options": [{"label": "A", "text": "Type 16&18 are high-risk", "correct": false}, {"label": "B", "text": "High-risk HPVs are also implicated in SCC arising at many other sites", "correct": false}, {"label": "C", "text": "It preferentially Infects mature squamous epithelial cells", "correct": true}, {"label": "D", "text": "The cancer-producing capability is because of E6 and E7 protein", "correct": false}], "correct_answer": "C. It preferentially Infects mature squamous epithelial cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It preferentially Infects mature squamous epithelial cells HPV infection primarily affects basal cells of the squamous epithelium, not mature squamous cells. The virus enters the basal cells and disrupts their normal growth and differentiation, leading to abnormal cell changes and potential progression to cancer.</p>\n<p><strong>Highyeild:</strong></p><p>Pathogenesis of HPV infection in cervix Transmission : Sexual contact : including vaginal, anal, and oral sex. Epithelial entry: virus enters the cervical epithelium through micro-abrasions or disruptions in the epithelial barrier , usually at the transformation zone Viral replication : Infects the basal cells of the cervical epithelium. The viral genome enters the nucleus of the basal cells and begins replicating. E6 and E7 proteins : They interfere with the normal cell cycle regulation and promote cell proliferation. E6 : Binds with p53 gene and promotes degradation E7: Binds with RB gene and promotes degradation Cellular changes : Development of koilocytes and dysplasia Progression to cervical cancer</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Type 16 and 18 are high risk: True statement. Human papillomavirus (HPV) types 16 and 18 are considered high-risk types as they are associated with an increased risk of developing cervical cancer. Option: B. High-risk HPVs are also implicated in SCC arising at many other sites: True statement. In addition to cervical cancer, high-risk HPVs, including types 16 and 18, are also implicated in the development of squamous cell carcinomas in other sites such as the anus, vulva, vagina, penis, and oropharynx. Option: D. The cancer-producing capability is because of E6 and E7 proteins: True statement. These proteins interfere with cell cycle regulation and promote the degradation of tumor suppressor proteins, allowing infected cells to proliferate and evade normal cellular control mechanisms.</p>\n<p><strong>Extraedge:</strong></p><p>HPV strains Disease HPV type associated with the disease Cutaneous Plantar Wart 1,2 Common Wart 2,1 Flat Wart 3, 10 Butcher's wart 7,2 Genital Bowen's disease (intraepithelial neoplasm) 16 (Genital) 2, 3, 4, 16 (Extragenital) Epidermodysplasia verruciformis (full skin 2, 3, 5, 8, 9 thickness wart can become squamous cell cancer) 10, 12, 14, 15, 17 Condylomata acuminata (venereal or genital warts) Intraepithelial neoplasms Low grade 6, 11 High grade 16, 18 Respiratory papillomatosis (transmitted from mother to baby) 6,11</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most common HPV stereotype associated with Adenocarcinoma of the cervix?", "options": [{"label": "A", "text": "16", "correct": false}, {"label": "B", "text": "18", "correct": true}, {"label": "C", "text": "31", "correct": false}, {"label": "D", "text": "33", "correct": false}], "correct_answer": "B. 18", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>18 HPV-18 is known to be strongly associated with the development of cervical adenocarcinoma. It is one of the high-risk HPV genotypes that can lead to the progression of cervical lesions to invasive adenocarcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Association of HPV serotypes and carcinoma cervix Most common stereotype: HPV 16 Most malignant serotype: HPV 18 Most specific serotype: HPV 18 Most common stereotype associated with Adenocarcinoma: HPV 18 Squamous cell carcinoma: HPV 16</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. HPV-16: It is the most common high-risk HPV genotype and is strongly associated with the development of squamous cell carcinoma of the cervix. Option:C. HPV-31: It is a high-risk HPV genotype that can contribute to the development of cervical cancer. While it is less common than HPV-16 and HPV-18, it is still considered a significant risk factor for cervical malignancies. Option:D. HPV-33: It is another high-risk HPV genotype that is associated with cervical cancer. It is less prevalent compared to HPV-16 and HPV-18.</p>\n<p><strong>Extraedge:</strong></p><p>HPV strains Disease HPV type associated with the disease Cutaneous Plantar Wart 1,2 Common Wart 2,1 Flat Wart 3, 10 Butcher's wart 7,2 Genital Bowen's disease (intraepithelial neoplasm) 16 (Genital) 2, 3, 4, 16 (Extragenital) Epidermodysplasia verruciformis (full skin 2, 3, 5, 8, 9 thickness wart can become squamous cell cancer) 10, 12, 14, 15, 17 Condylomata acuminata (venereal or genital warts) Intraepithelial neoplasms Low grade 6, 11 High grade 16, 18 Respiratory papillomatosis (transmitted from mother to baby) 6,11</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What are the features of pilocytic change caused by HPV?", "options": [{"label": "A", "text": "Nuclear enlargement", "correct": false}, {"label": "B", "text": "Nuclear hyperchromasia", "correct": false}, {"label": "C", "text": "Perinuclear halo", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Nuclear enlargement, Nuclear hyperchromasia, and Perinuclear halo are all features of Koilocytic changes caused by HPV. Hence, the correct answer is D. All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Features of pilocytic change caused by HPV Nuclear enlargement : Koilocytes exhibit enlarged nuclei compared to the surrounding cells. The nuclei may appear irregular in shape and size. Nuclear hyperchromasia : Koilocytes often display increased nuclear staining, leading to hyperchromatic nuclei. The nuclei appear darker or more intensely stained compared to the surrounding cells. Perinuclear halo: One of the characteristic features of koilocytes is the presence of a perinuclear halo or clear zone surrounding the nucleus. This halo is caused by cytoplasmic vacuolization or clearing around the nucleus. Irregular nuclear contours : The nuclei of koilocytes may have irregular or uneven borders, contributing to their characteristic appearance. Binucleation or multinucleation : Koilocytes can sometimes have multiple nuclei within a single cell, leading to the presence of binucleated or multinucleated cells. Cytoplasmic vacuolization: The cytoplasm of koilocytes may contain vacuoles or clear spaces, giving the cells a bubbly or frothy appearance. Indistinct cell borders : Koilocytes often have indistinct or blurred cell borders due to cytoplasmic changes and vacuolization.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "At the ultrastructural level, the perinuclear halo shows the cytoplasmic effect of which viral protein?", "options": [{"label": "A", "text": "E5", "correct": true}, {"label": "B", "text": "E6", "correct": false}, {"label": "C", "text": "E7", "correct": false}, {"label": "D", "text": "E8", "correct": false}], "correct_answer": "A. E5", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>E5 The perinuclear halo observed at the ultrastructural level in infected cells is associated with the cytoplasmic effect of the E5 viral protein of HPV (Human Papillomavirus).</p>\n<p><strong>Highyeild:</strong></p><p>HPV genome organization</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. E6: The E6 protein of HPV plays a crucial role in the degradation of the tumor suppressor protein p53. While E6 is involved in various cellular changes associated with HPV infection, it is not directly responsible for the perinuclear halo effect. Option: C. E7: The E7 protein of HPV binds to and inactivates the retinoblastoma protein (pRB), leading to dysregulation of the cell cycle. Similar to E6, E7 is involved in various cellular changes but not specifically linked to the perinuclear halo effect. Option: D. E8: There is no known HPV viral protein called E8.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following would not be seen in a colonoscopies biopsy of a patient with cervical intraepithelial neoplasia?", "options": [{"label": "A", "text": "Dysplasia", "correct": false}, {"label": "B", "text": "Breach in basement membrane", "correct": true}, {"label": "C", "text": "Altered N: C ratio", "correct": false}, {"label": "D", "text": "Mitotic figures", "correct": false}], "correct_answer": "B. Breach in basement membrane", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Breach in basement membrane A breach in the basement membrane is not typically observe d in cervical intraepithelial neoplasia (CIN). CIN represents abnormal cellular changes within the cervical epithelium.</p>\n<p><strong>Highyeild:</strong></p><p>Features of CIN: Varying degree of dysplasia Altered nuclear-cytoplasmic ratio Hyperchromatic nuclei Mitotic figures Intact basement membrane</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., C., D: All are features of CIN</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the characteristic cytological findings on PAP smear examination in a 26-year-old female presented for screening. What’s your diagnosis?", "options": [{"label": "A", "text": "LSIL", "correct": true}, {"label": "B", "text": "HSIL", "correct": false}, {"label": "C", "text": "Squamous cell carcinoma", "correct": false}, {"label": "D", "text": "Adenocarcinoma", "correct": false}], "correct_answer": "A. LSIL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>LSIL The given image of PAP cytology shows a low nuclear-to-cytoplasmic ratio, nuclear irregularity, hyperchromasia, perinuclear halo, and binucleation which are suggestible of cellular changes seen in low-grade lesions. LSIL represents mild dysplastic changes in the squamous epithelial cells, indicating a lower risk for the development of invasive squamous cell carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>PAP cytology</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. HSIL: It typically exhibits more pronounced cellular abnormalities, including increased nuclear-to-cytoplasmic ratio, severe nuclear irregularities, and more significant cytological atypia. Option: C. Squamous cell carcinoma: It is characterized by the presence of malignant squamous epithelial cells showing features such as severe nuclear abnormalities, disordered architecture, and invasive behavior. Option: D. Adenocarcinoma: It is a malignancy arising from glandular cells which typically exhibit glandular formations or mucin production.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the histological features of a cervical biopsy showing tumor infiltration into the stroma, the diagram is shown below, Identify the type of tumor:", "options": [{"label": "A", "text": "Adenocarcinoma", "correct": false}, {"label": "B", "text": "Squamous cell carcinoma", "correct": true}, {"label": "C", "text": "Basaloid cell carcinoma", "correct": false}, {"label": "D", "text": "Small cell carcinoma", "correct": false}], "correct_answer": "B. Squamous cell carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686835069948-QTDP154008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Squamous cell carcinoma The histopathological image showing nests and tongues of malignant squamous epithelium infiltrating the stroma is suggestive of squamous cell carcinoma. It is the most common type of cervical cancer and is characterized by the presence of malignant squamous epithelial cells invading the surrounding stromal tissue.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. Adenocarcinoma: It typically presents with glandular differentiation and the formation of glandular structures. It is characterized by the presence of malignant glandular cells. Option:C. Basaloid cell carcinoma: It is a variant of squamous cell carcinoma characterized by small basaloid cells with a high nuclear-cytoplasmic ratio and peripheral palisading. Option:D. Small cell carcinoma: It is a neuroendocrine tumor that can occur in various organs. Small cell carcinoma typically shows small, uniform cells with a high nuclear-cytoplasmic ratio and a characteristic neuroendocrine appearance.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are risk factors for breast cancer except:", "options": [{"label": "A", "text": "Early menarche", "correct": false}, {"label": "B", "text": "Estrogen exposure", "correct": false}, {"label": "C", "text": "Nullipara", "correct": false}, {"label": "D", "text": "Early pregnancy", "correct": true}], "correct_answer": "D. Early pregnancy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Early pregnancy Early pregnancy is not considered a risk factor for breast cancer. In fact, early pregnancy has been associated with a decreased risk of breast cancer</p>\n<p><strong>Highyeild:</strong></p><p>Risk factors for Breast cancer Risk factors Explanation Age The risk of breast cancer increases with age, with the majority of cases occurring in women over the age of 50. Family History Having a first-degree relative (parent, sibling, or child) with breast cancer increases the risk, especially if the relative was diagnosed at a young age. BRCA1 and BRCA2 Mutations Inherited mutations in the BRCA1 and BRCA2 genes significantly increase the risk of developing breast and ovarian cancers. Personal History of Breast Cancer Women who have previously been diagnosed with breast cancer have a higher risk of developing a second breast cancer. Early Menarche Starting menstruation at an early age (before 12 years) is associated with a slightly increased risk of breast cancer. Late Menopause Women who experience menopause at a later age (after 55 years) have a higher risk of breast cancer. Nulliparity Never having given birth to a child increases the risk of breast cancer Late Age at First Full-Term Pregnancy Women who have their first full-term pregnancy after the age of 30 have a slightly higher risk of breast cancer. Hormone Replacement Therapy Long-term use of hormone replacement therapy (HRT) containing estrogen and progesterone is associated with an increased risk of breast cancer. Alcohol Consumption Regular and excessive alcohol consumption is a known risk factor for breast cancer.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Early menarche: Women who start menstruating at a younger age have a longer lifetime exposure to estrogen and other hormones, which may contribute to an increased risk of breast cancer. Option: B. Estrogen exposure: Prolonged exposure to estrogen, whether through hormone replacement therapy, use of oral contraceptives, or estrogen-related conditions, such as polycystic ovary syndrome (PCOS), has been associated with an increased risk of breast cancer. Option: C. Nullipara: Women who have not had children have a slightly higher risk of developing breast cancer compared to those who have had children, especially if they have not breastfed.</p>\n<p><strong>Extraedge:</strong></p><p>Protective factors that lower the risk of breast cancer Breastfeeding Physical activity Normal BMI Regular screening</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 32-year-old woman presents with a lump in the breast in the upper and outer quadrants. Histopathology shows sheets of pleomorphic cells with mitotic figures and lymphoplasmacytic infiltrate. What is the most likely diagnosis?", "options": [{"label": "A", "text": "Lobular carcinoma", "correct": false}, {"label": "B", "text": "Medullary carcinoma", "correct": true}, {"label": "C", "text": "Papillary carcinoma", "correct": false}, {"label": "D", "text": "Colloid carcinoma", "correct": false}], "correct_answer": "B. Medullary carcinoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Medullary carcinoma The given clinical scenario and histopathological findings are suggestive of Medullary carcinoma of the breast. It is a subtype of invasive breast carcinoma. It typically presents as a well-circumscribed mass in the breast, often in the upper and outer quadrants. The characteristic lymphoplasmacytic infiltrate and the presence of pleomorphic cells with mitotic figures are important histopathological features of medullary carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Lobular carcinoma: It typically shows a discohesive growth pattern with individual cells infiltrating the stroma. Option: C. Papillary carcinoma: It is characterized by finger-like projections of tumor cells surrounded by fibrovascular cores. Option: D. Colloid carcinoma: It is characterized by abundant extracellular mucin.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following lesions arise from lobules and terminal ducts of the breast? Carcinoma breast Fibroadenoma Sclerosing adenosis Periductal mastitis Blue dome cyst Select the correct answer from given below code:", "options": [{"label": "A", "text": "1,2,3 correct", "correct": false}, {"label": "B", "text": "1,3,5 correct", "correct": true}, {"label": "C", "text": "2,4,5 correct", "correct": false}, {"label": "D", "text": "2,4 correct", "correct": false}], "correct_answer": "B. 1,3,5 correct", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>1,3,5 correct Among the given Options- Carcinoma breast, Sclerosing adenosis, and Blue dome cyst arise from terminal duct lobular unit (TLDU) TLDU is the functional unit of the breast.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - 2. Fibroadenoma: Arises from lobular stromatolites 4. Periductal mastitis: Arises from large lactiferous duct</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following markers can be used to differentiate Ductal carcinoma in-situ from invasive carcinoma?", "options": [{"label": "A", "text": "HER2", "correct": false}, {"label": "B", "text": "p53", "correct": false}, {"label": "C", "text": "ER", "correct": false}, {"label": "D", "text": "p63", "correct": true}], "correct_answer": "D. p63", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>p63 Ductal carcinoma in-situ (DCIS) is a non-invasive form of breast cancer where the abnormal cells are confined within the milk ducts and have not spread into the surrounding breast tissue. Invasive carcinoma, on the other hand, refers to cancer cells that have broken through the ductal walls and invaded the surrounding breast tissue. p63 is a marker that can aid in distinguishing between these two conditions.</p>\n<p><strong>Highyeild:</strong></p><p>Ductal carcinoma in situ It refers to non-invasive breast cancer that is confined to the ducts of the breast. Origin: Epithelial cells that line the milk ducts of the breast. Growth pattern: Often exhibits a ductal growth pattern, with abnormal cells proliferating within the ductal system. Features: Palpable mass or nipple discharge in some cases. Mammographic Findings: Microcalcifications or architectural distortion Potential to progress to invasive ductal carcinoma (IDC)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. HER2: It is an important marker for breast cancer subtyping and treatment decisions, it does not specifically differentiate between DCIS and invasive carcinoma. Option:B. p53:p53 is a tumor suppressor protein that regulates cell growth and prevents tumor formation, Both DCIS and invasive carcinoma may show p53 alterations and hence cannot be used to differentiate. Option:C. ER: Both DCIS and invasive carcinoma can exhibit variable ER expression patterns</p>\n<p><strong>Extraedge:</strong></p><p>DCIS Vs LCIS Characteristics DCIS LCIS Structure involved Ducts Lobules Type of subsequent cancer Ductal Ductal or lobular Site of origin Unicentric Multicentric Breast at risk for invasive cancer Ipsilateral breast Either breast Laterality Unilateral Often bilateral</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old female presents with persistent itching, redness, and scaling of the right nipple for the past few months. She also complains of occasional mild nipple discharge. On examination, the right nipple appears erythematous, with crusting and scaling involving the areola. The left nipple appears normal. The patient has no palpable breast masses. Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Paget's disease of the breast", "correct": true}, {"label": "B", "text": "Inflammatory breast cancer", "correct": false}, {"label": "C", "text": "Mastitis", "correct": false}, {"label": "D", "text": "Eczema", "correct": false}], "correct_answer": "A. Paget's disease of the breast", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Paget's disease of the breast The given clinical scenario is suggestive of Paget’s disease of the breast. It is a rare form of breast cancer that typically presents with symptoms such as persistent itching, redness, and scaling of the nipple and areola.</p>\n<p><strong>Highyeild:</strong></p><p>Paget’s disease of breast Paget cell = Intraepithelial adenocarcinoma cells Presents as eczema-like changes in the nipple and surrounding area. Age: Women of 50 years of age Symptoms: redness, itching, scaling, crusting, or thickening of the nipple or areola. The affected nipple may appear flattened, inverted, or ulcerated. Often associated with an underlying ductal carcinoma, either in situ ( DCIS) or invasive carcinoma . Biopsy is done for diagnosis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Inflammatory breast cancer: It is a rare and aggressive form of breast cancer that typically presents with symptoms such as rapid onset of redness, swelling, warmth, and thickening of the breast. The skin may have an \"orange peel\" appearance, and there may be associated breast enlargement or heaviness. Option: C. Mastitis: It is an infection of the breast tissue that can occur in women, typically during breastfeeding. It presents with symptoms such as breast pain, swelling, redness, and warmth. There may be associated fever and flu-like symptoms that can cause nipple discharge Option: D. Eczema: It is a common skin condition characterized by itching, redness, and scaling. It can affect various parts of the body, including the nipple and areola. However, localized involvement of the right nipple with crusting and scaling, along with persistent itching and nipple discharge, is suggestive of Paget's disease rather than eczema.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding LCIS except:", "options": [{"label": "A", "text": "Tumor cells are uniform having round to oval nuclei", "correct": false}, {"label": "B", "text": "On IHC it shows loss of adhesion molecules E-cadherin", "correct": false}, {"label": "C", "text": "Mucin-positive signet-ring cells are commonly present", "correct": false}, {"label": "D", "text": "It shows calcification and stromal reaction", "correct": true}], "correct_answer": "D. It shows calcification and stromal reaction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It shows calcification and stromal reaction Lobular Carcinoma In Situ (LCIS) is a non-invasive form of breast cancer that starts in the milk-producing glands (lobules) of the breast. It does not typically produce calcifications on mammography. Additionally, it does not elicit a significant stromal reaction.</p>\n<p><strong>Highyeild:</strong></p><p>Lobular Carcinoma In Situ (LCIS) It is a non-invasive form of breast cancer. Bilateral involvement: often a multicentric Lack of mass or palpable lump Discohesive growth pattern: lack the adhesion molecule E-cadherin Uniform cell morphology: Cells cells in LCIS are small and uniform, with a round to oval nuclei Increased risk of invasive breast cancer</p>\n<p><strong>Extraedge:</strong></p><p>DCIS Vs LCIS Characteristics DCIS LCIS Structure involved Ducts Lobules Type of subsequent cancer Ductal Ductal or lobular Site of origin Unicentric Multicentric Breast at risk for invasive cancer Ipsilateral breast Either breast Laterality Unilateral Often bilateral</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the molecular classification which class of breast carcinoma is most common:", "options": [{"label": "A", "text": "ER +ve, Her2neu -ve", "correct": true}, {"label": "B", "text": "ER +ve, Her2neu +ve", "correct": false}, {"label": "C", "text": "ER +ve, Her2neu + ve", "correct": false}, {"label": "D", "text": "ER -ve, Her2neu -ve", "correct": false}], "correct_answer": "A. ER +ve, Her2neu -ve", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>ER +ve, Her2neu -ve ER +ve, Her2neu -ve : often referred to as Luminal A is the most common subtype of breast carcinoma It is generally associated with a better prognosis compared to the other subtypes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:B. ER +ve, Her2neu +ve: This subtype, known as Luminal B, is characterized by positive expression of both estrogen receptor (ER) and Her2neu. It represents a smaller proportion of breast carcinomas compared to Luminal A Option:C. ER -ve, Her2neu +ve: This subtype is called Her2-enriched. It represents a relatively smaller proportion of breast carcinomas but is associated with aggressive tumor behavior. Option:D. ER -ve, Her2neu -ve: This subtype, is referred to as Triple-negative breast cancer (TNBC). It represents a significant proportion of breast carcinomas, particularly in younger women, and is associated with a more aggressive clinical course.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Nottingham Histologic Score includes all of the mentioned parameters except:", "options": [{"label": "A", "text": "Tubule formation", "correct": false}, {"label": "B", "text": "Pleomorphism", "correct": false}, {"label": "C", "text": "Mitotic rate", "correct": false}, {"label": "D", "text": "Area of necrosis", "correct": true}], "correct_answer": "D. Area of necrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Area of necrosis The Nottingham Histologic Score does not include the assessment of necrosis as a separate parameter. It is a scoring system used to assess the grade of breast carcinoma based on three histological features: tubule formation, nuclear pleomorphism, and mitotic count.</p>\n<p><strong>Highyeild:</strong></p><p>Nottingham Histologic Score Histologic Feature Score Tubule Formation 1 (well-formed), 2 (intermediate), 3 (poorly formed or absent) Nuclear Pleomorphism 1 (mild), 2 (moderate), 3 (marked) Mitotic Count 1 (low), 2 (intermediate), 3 (high) Total score Grade 3-5 Grade 1 (well-differentiated) 6-7 Grade 2 (moderately differentiated) 8-9 Grade 3 (poorly differentiated)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Lobular carcinoma of the breast can be identified on IHC by lack of expression of which marker in tumor cell?", "options": [{"label": "A", "text": "ER", "correct": false}, {"label": "B", "text": "PR", "correct": false}, {"label": "C", "text": "Ki67", "correct": false}, {"label": "D", "text": "E cadherin", "correct": true}], "correct_answer": "D. E cadherin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>E cadherin Lobular carcinoma of the breast is characterized by a loss or reduced expression of E-cadherin , which is a cell adhesion molecule. E-cadherin plays a crucial role in maintaining the cohesive structure of epithelial cells by mediating cell-to-cell adhesion.</p>\n<p><strong>Highyeild:</strong></p><p>Lobular Breast Carcinoma Incidence : Accounts for approximately 10-15% of all invasive breast cancers. Growth pattern: It is characterized by a discohesive growth pattern , meaning that the tumor cells do not adhere tightly to each other and often show a scattered or single-file arrangement. E-cadherin loss : Associated with a loss or reduced expression of E-cadherin, a cell adhesion molecule. Bilateral involvement : This bilaterality can occur synchronously or metachronously. Multifocality and multicentricity: Lobular carcinoma often presents as a multifocal or multicentric disease within the same breast. This means that multiple tumor foci can be present within the breast, either in the same quadrant or in different quadrants. Imaging: It often presents subtle architectural distortions or ill-defined asymmetries. Hormone receptor status: ER-positive and/or PR-positive HER2 status: Lobular carcinoma is typically HER2-negative, with a lower frequency of HER2 overexpression/amplification compared to invasive ductal carcinoma. Clinical presentation: Lobular carcinoma may present as a palpable breast lump, breast asymmetry, nipple changes, or mammographic abnormalities.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following most commonly performed IHC shows a membranous pattern of staining?", "options": [{"label": "A", "text": "ER", "correct": false}, {"label": "B", "text": "PR", "correct": false}, {"label": "C", "text": "Ki67", "correct": false}, {"label": "D", "text": "Her2neu", "correct": true}], "correct_answer": "D. Her2neu", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Her2neu Her2neu is a cell surface receptor that is overexpressed or amplified in certain breast cancers. The IHC staining for Her2neu typically shows a membranous staining pattern, meaning the staining is localized to the cell membrane</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. And B: ER (estrogen receptor) and PR (progesterone receptor) are nuclear receptors, and their IHC staining typically shows nuclear staining, indicating the presence or absence of receptor expression in the nuclei of tumor cells. Option: C. Ki67: It is a protein marker that is used as a proliferation marker in tumor cells. The staining for Ki67 is typically observed in the nuclei of proliferating cells, and the pattern is not membranous.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The presence of discohesive infiltrating tumor cells, often including signet-ring cells, and lack of desmoplastic reaction are characteristic histological features of-", "options": [{"label": "A", "text": "Invasive ductal carcinoma", "correct": false}, {"label": "B", "text": "Lobular carcinoma", "correct": true}, {"label": "C", "text": "Medullary carcinoma", "correct": false}, {"label": "D", "text": "Papillary carcinoma", "correct": false}], "correct_answer": "B. Lobular carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689581332279-QTDP159012IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lobular carcinoma The given histological features, including the presence of discohesive infiltrating tumor cells , often including signet-ring cells, and the lack of desmoplastic reaction , are characteristic of lobular carcinoma of the breast. The tumor cells in lobular carcinoma have a discohesive appearance, meaning they do not adhere tightly to each other, resulting in a scattered pattern. This can give the tumor cells a single-file or Indian-file appearance.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Invasive ductal carcinoma: The most common type of breast carcinoma, is characterized by the infiltration of malignant cells through the breast ducts. It typically shows a desmoplastic reaction and may exhibit a variety of histological patterns. Option:C. Medullary carcinoma: It is characterized by the presence of solid, syncytium-like sheets of large cells with pleomorphic nuclei and a prominent lymphocytic infiltrate. Option:D. Papillary carcinoma: It is characterized by the presence of papillary structures within the tumor. It typically exhibits fibrovascular cores covered by neoplastic epithelial cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of medullary carcinoma of the breast except:", "options": [{"label": "A", "text": "Presence of solid,syncytium-like sheets of large cells with pleomorphic nuclei, and prominent nucleoli", "correct": false}, {"label": "B", "text": "Frequent mitosis", "correct": false}, {"label": "C", "text": "Lympho-plasmacytic infiltrate around and into the tumor", "correct": false}, {"label": "D", "text": "Infiltrative border", "correct": true}], "correct_answer": "D. Infiltrative border", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689581332432-QTDP159013IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Infiltrative border Medullary carcinoma is known for having well-defined borders rather than infiltrative borders. The tumor cells are typically compactly arranged and exhibit pushing margins, meaning they do not invade the surrounding stroma as aggressively as some other types of breast carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Histological feature of medullary carcinoma Syncytial growth pattern: Medullary carcinoma is characterized by the presence of solid, syncytium-like sheets of large tumor cells. These cells are tightly packed together and have indistinct cell borders. Pleomorphic nuclei : The nuclei may be large, irregularly shaped, and show prominent nucleoli. High mitotic rate: Exhibits a high mitotic rate, with many dividing cells observed under the microscope. Lymphocytic infiltrate: One of the hallmark features of medullary carcinoma is the presence of a prominent lymphocytic infiltrate surrounding and infiltrating the tumor. This infiltrate is composed of lymphocytes and plasma cells and can give the tumor a lymphoid-like appearance. Well-defined borders: Medullary carcinoma is known for having well-demarcated borders, meaning the tumor cells are compactly arranged and exhibit pushing margins rather than infiltrative borders. This characteristic helps differentiate it from other types of invasive breast carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Presence of solid, syncytium-like sheets of large cells with pleomorphic nuclei and prominent nucleoli: Medullary carcinoma is characterized by the presence of large tumor cells arranged in syncytial sheets. These cells have pleomorphic nuclei and prominent nucleoli. Option: B. Frequent mitosis: Medullary carcinoma often exhibits a high mitotic rate, meaning there are many dividing cells observed under the microscope. Option: C. Lympho-plasmacytic infiltrates around and into the tumor: A distinguishing feature of medullary carcinoma is the presence of a prominent lymphocytic and plasma cell infiltrate around and within the tumor. This infiltrate gives a lymphoid-like appearance and can be seen surrounding the tumor cells.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 55-year-old female patient presented with a breast lump which on mammogram shows calcification. A histopathological picture of the breast biopsy is shown below. Based on the histological features identify the tumor:", "options": [{"label": "A", "text": "Invasive ductal carcinoma", "correct": true}, {"label": "B", "text": "Lobular carcinoma", "correct": false}, {"label": "C", "text": "Medullary carcinoma", "correct": false}, {"label": "D", "text": "Secretory carcinoma", "correct": false}], "correct_answer": "A. Invasive ductal carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689581332649-QTDP159014IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Invasive ductal carcinoma The given histopathological image showing small glandular, duct-like cells in a desmoplastic stroma is suggestive of invasive ductal carcinoma, which is the most common type of breast carcinoma. The presence of calcifications on mammograms is a common finding in IDC, as calcifications can develop within the tumor or in the surrounding tissue.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Lobular carcinoma: It is characterized by the growth of malignant cells within the lobules of the breast, rather than in the ducts. It typically shows a characteristic \"Indian file\" pattern of cells, with single-file infiltration. Option: C. Medullary carcinoma: It is a type of invasive ductal carcinoma characterized by the presence of large, pleomorphic tumor cells with syncytial growth patterns and a lymphocytic infiltrate. Option: D. Secretory carcinoma: It is a rare subtype that typically affects younger individuals. It is characterized by the presence of intracellular and extracellular secretions within the tumor.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most common benign tumor of the breast is-", "options": [{"label": "A", "text": "Phyllodes", "correct": false}, {"label": "B", "text": "Angiosarcoma", "correct": false}, {"label": "C", "text": "Fibroadenoma", "correct": true}, {"label": "D", "text": "Fibromatosis", "correct": false}], "correct_answer": "C. Fibroadenoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fibroadenoma Fibroadenomas are the most common benign tumor of the female breast. They typically appear as a smooth, firm, rubbery mass that can move around within the breast.</p>\n<p><strong>Highyeild:</strong></p><p>Fibroadenoma Most common benign tumor of breast Occurs in females <35 years old Feature: Small, well-defined, mobile mass Tumour composed of fibrous tissue and glands Increase in size with an increase in estrogen ( pregnancy, prior to menstruation)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Phyllodes: These tumors are rare fibroepithelial tumors of the breast. They are typically larger than fibroadenomas and have characteristic leaf-like projections within the tumor. Option: B. Angiosarcoma: It is a malignant tumor that arises from the cells lining blood vessels or lymphatic vessels. Option: D. Fibromatosis: Also known as desmoid tumors, fibromatosis is a rare benign tumor that arises from fibrous tissue. It tends to infiltrate surrounding tissues and can be locally aggressive, but it does not have the potential to spread to other parts of the body.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A histological image from a breast lesion is shown below. What is the likely diagnosis?", "options": [{"label": "A", "text": "Fibroadenoma", "correct": false}, {"label": "B", "text": "Liposarcoma", "correct": false}, {"label": "C", "text": "Phyllodes", "correct": true}, {"label": "D", "text": "Angiosarcoma", "correct": false}], "correct_answer": "C. Phyllodes", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689581332931-QTDP159016IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Phyllodes The given histological image showing stromal overgrowth, high cellularity, mitosis, and leaflets-like architecture , are characteristic of a phyllodes tumor. Phyllodes tumors are rare fibroepithelial tumors of the breast that primarily arise from the stromal tissue. They typically display leaf-like projections or leaflets on microscopic examination, which correspond to the cleft-like spaces within the tumor.</p>\n<p><strong>Highyeild:</strong></p><p>Phyllodes tumor of breast Phyllon = leaf , Sarcoma = fleshy tumor Age: Over 40 years ago Mostly benign Features: Large (bag 5cm) tumor Unilateral Rapidly growing mass Ulceration of overlying skin Histology: Leaf-like lobulations</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fibroadenoma: Fibroadenomas are the most common benign breast tumors. They typically exhibit a biphasic pattern of epithelial and stromal components, but they do not show the leaflet-like architecture, stromal overgrowth, or high cellularity seen in phyllode tumors. Option: B. Liposarcoma: Liposarcomas are malignant tumors arising from adipose tissue, not from stromal tissue as seen in the image. Option: D. Angiosarcoma: Angiosarcoma is a rare malignant tumor that arises from the blood vessels. It typically presents as an infiltrative lesion with vascular channels.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 50 years old woman has been diagnosed with breast carcinoma. IHC staining of tissue biopsy specimens of this patient shows ER+/PR+ and HER2-. Which of the following statements is true regarding her condition?", "options": [{"label": "A", "text": "Good response to trastuzumab", "correct": false}, {"label": "B", "text": "Poor response to paclitaxel", "correct": true}, {"label": "C", "text": "Associated with tp53 mutation", "correct": false}, {"label": "D", "text": "BRCA 1 mutation is most probable", "correct": false}], "correct_answer": "B. Poor response to paclitaxel", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Poor response to paclitaxel The given clinical history go ER+/PR+ and HER2- breast cancer, is suggestive of luminal A molecular subtype. Luminal A molecular subtype shows poor response to paclitaxel</p>\n<p><strong>Highyeild:</strong></p><p>Molecular subtype and associated mutations Subtype Mutations Luminal A PIK3CA mutation , BRCA2 mutation Luminal B TP53 mutations, PIK3CA mutations, BRCA2 mutation HER2-enriched HER2 gene amplification, TP53 mutations Basal-like (Triple-Negative) BRCA1/BRCA2 mutations, TP53 mutations</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. Good response to trastuzumab: Wrong statement. Trastuzumab is a recombinant humanized monoclonal antibody directed against HER-2 Option:C. Associated with tp53 mutation: Wrong statement. Tp53 mutations are associated with triple-negative tumors Option:D .BRCA 1 mutation is most probable: Wrong statement. Luminal A subtype is more commonly associated with BRCA2 mutation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The pictures below show breast biopsy specimens on which immunohistochemical for ER, PR, and Her2 neu have been done. This molecular subtype includes all of the following?", "options": [{"label": "A", "text": "Medullary carcinoma", "correct": false}, {"label": "B", "text": "Mucinous carcinoma", "correct": true}, {"label": "C", "text": "Adenoid cystic carcinoma", "correct": false}, {"label": "D", "text": "Secretory carcinoma", "correct": false}], "correct_answer": "B. Mucinous carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689581332066-QTDP157020IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mucinous carcinoma The given image shows the breast tissue negatively stained for all three i.e. ER, PR, and Her2 neu . (called Triple negative ) Mucinous carcinomas are usually ER-positive and HER2/neu negative</p>\n<p><strong>Highyeild:</strong></p><p>Triple negative molecular subtypes commonly include the following histologic subtypes: Medullary Adenoid cystic Secretory Spindle cell Squamous Metaplastic Matrix-producing</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A., C., D: Medullary carcinoma, Adenoid cystic carcinoma, and secretory carcinoma are all subtypes of breast cancer that can exhibit a triple-negative phenotype.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 27 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following tests mentioned below are related to the synthetic function of hepatocytes except:", "options": [{"label": "A", "text": "Serum albumin", "correct": false}, {"label": "B", "text": "Prothrombin time", "correct": false}, {"label": "C", "text": "Serum ammonia", "correct": false}, {"label": "D", "text": "Serum γ-glutamyl transpeptidase", "correct": true}], "correct_answer": "D. Serum γ-glutamyl transpeptidase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serum γ-glutamyl transpeptidase Serum γ-glutamyl transpeptidase (GGT) is related to the excretory function of liver hepatocyte</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Albumin: It is a protein synthesized by hepatocytes, and its levels can be reduced in conditions such as liver cirrhosis, where there is impaired synthetic function. Option: B .Prothrombin time: It measures the time it takes for the blood to clot and is dependent on the liver's ability to produce clotting factors. Option C .Serum ammonia: It is a test that measures the liver's ability to convert ammonia to urea and eliminate it from the body. High levels of ammonia in the blood can indicate liver dysfunction.</p>\n<p><strong>Table:</strong></p><p>Serum markers in liver pathology A. Enzymes released in liver damage Aspartate aminotransferase Increased in most liver diseases. ALT >\n AST Alanine aminotransferase In alcoholic liver disease: AST>ALT\n (>2:1) AST>ALT in non-alcoholic liver disease\n suggests progression to advanced fibrosis or cirrhosis Alkaline phosphatase Increased in cholestasis, infiltration\n disorders, bone disease Gamma - glutamyl phosphatase Increased in various liver and biliary\n diseases Associated with alcohol use Functional liver markers Bilirubin Increased in various liver diseases, hemolysis Albumin Decreased in advanced liver disease Prothrombin time Increased in advanced liver disease platelets Decreased in advanced liver disease and portal\n hypertension</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statement are true regarding acute liver injury:", "options": [{"label": "A", "text": "Also called fulminant hepatic failure", "correct": false}, {"label": "B", "text": "Liver is small and shrunken", "correct": false}, {"label": "C", "text": "Massive hepatic necrosis", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Acute liver injury refers to a sudden and severe impairment of liver function.It can have a range of presentations and severity levels. All the statements given above are true with respect to Acute liver injury, hence the answer D: All of the above is the correct option.</p>\n<p><strong>Highyeild:</strong></p><p>Acute liver injury Acute liver injury is a sudden and severe deterioration of liver function. It can also be referred to as fulminant hepatic failure. The liver may become small and shrunken due to massive hepatic necrosis. Massive hepatic necrosis is the widespread death of liver cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A. Also called fulminant hepatic failure: Fulminant hepatic failure is a specific subset of acute liver injury characterized by rapid progression and severe liver dysfunction. Option:B. Liver is small and shrunken: In some cases of acute liver injury, the liver can indeed become small and shrunken. This can occur due to extensive damage and loss of liver cells, leading to liver atrophy. Option:C. Massive hepatic necrosis: It is a hallmark feature of acute liver injury. It refers to widespread death of liver cells, resulting in extensive tissue damage and loss of liver function.</p>\n<p><strong>Extraedge:</strong></p><p>Acute liver injury can lead to the development of coagulopathy and hepatic encephalopathy.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true except", "options": [{"label": "A", "text": "Lungs have a double arterial blood supply", "correct": false}, {"label": "B", "text": "Bronchioles have a cartilaginous ring", "correct": true}, {"label": "C", "text": "Blind end of the respiratory passage is the alveolar ducts and alveolar sac", "correct": false}, {"label": "D", "text": "Respiratory tree is lined by pseudostratified ciliated columnar epithelium except for the vocal cord", "correct": false}], "correct_answer": "B. Bronchioles have a cartilaginous ring", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bronchioles have a cartilaginous ring Bronchioles do not have cartilaginous rings . They have smooth muscle in their walls instead, which allows for their diameter to change during breathing.</p>\n<p><strong>Highyeild:</strong></p><p>Weibel model According to Weibel's lung model, there are 23 generations of airways. First 16 generation - Dead space Trachea is generation o (Go), this is a straight duct with a ring structure The first 16 generations make up the conducting airways ending in terminal bronchioles - Dead space The next three generations (17,18,19 )constitute the Respiratory bronchioles. The terminal bronchiole marks the end of the transition zone. Alveoli start appearing at Generation 17 Last 7 generations - Exchange airways</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Lungs have double arterial blood supply: This is true. The lungs receive blood from both the pulmonary arteries and the bronchial arteries. The pulmonary arteries carry deoxygenated blood from the heart to the lungs for oxygenation, while the bronchial arteries supply oxygenated blood to the lung tissue itself. Option: C . Blind end of the respiratory passage is the alveolar ducts and alveolar sac: This is true. The alveoli are where gas exchange occurs, with oxygen entering the bloodstream and carbon dioxide leaving it. Option: D . Respiratory tree is lined by pseudostratified ciliated columnar epithelium except for the vocal cord: This is also true. The respiratory epithelium consists of pseudostratified ciliated columnar epithelium, which helps to move mucus and debris out of the lungs. However, the vocal cords are lined by stratified squamous epithelium.</p>\n<p><strong>Table:</strong></p><p>Anatomy and Histology of respiratory pathway Airway region Epithelium Components in wall Functions Bronchi Respiratory Hyaline cartilage plates and smooth muscle Conduct air Bronchioles Simple cuboidal to columnar with cilia and club\n cells The first region lacking cartilage plates still contains smooth\n muscles Conduct air and undergo constriction and dilation Terminal bronchioles Simple cuboidal with cilia and club cells Smooth muscles but layers are thinner Conduct air and produce secretions that protect\n the airways and function as a surfactant Respiratory bronchioles Simple cuboidal with cilia and club cells,\n regions with alveolar epithelium Small bundles of smooth muscles Conduct air, produce secretions, and participate\n in some gas exchange Alveolar ducts Areas of simple cuboidal interspersed with\n alveolar epithelium Small, thin bundles of smooth muscles Conduct air and participate in gas exchange Alveoli Type I and II pneumocytes Reticular and elastic fibers The main site for gas exchange, surfactant\n production</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not true regarding pulmonary sequestration?", "options": [{"label": "A", "text": "It lacks connection with the airway system", "correct": false}, {"label": "B", "text": "It has an abnormal blood supply", "correct": false}, {"label": "C", "text": "They are not associated with other congenital anomalies", "correct": true}, {"label": "D", "text": "Extralobar sequestration is most common in infants", "correct": false}], "correct_answer": "C. They are not associated with other congenital anomalies", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>They are not associated with other congenital anomalies Pulmonary sequestration is often associated with other congenital anomalies, such as congenital heart defects, diaphragmatic hernias, and other anomalies of the lung or chest wall.</p>\n<p><strong>Highyeild:</strong></p><p>Pulmonary sequestration It is a rare congenital abnormality in which a portion of lung tissue develops without a connection to the normal bronchial tree. Classification : It can be classified as: intralobular sequestration : It is located within the normal lung tissue and shares the same pleura Extralobar sequestration : It is located outside the normal lung tissue and is often covered by its own pleura. Abnormal Blood Supply: Pulmonary sequestration receives its blood flow from systemic arteries instead of the normal pulmonary circulation . Symptoms : It may be asymptomatic, or it can present with respiratory symptoms such as recurrent pneumonia, cough, or chest pain. Extralobar sequestration may also present as a mass lesion. Diagnosis : Chest X-ray, CT scan, or MRI. Angiography may also be used to confirm the abnormal blood supply. Treatment : Surgical resection of the affected lung tissue. Embolization of the abnormal blood vessels Association with other anomalies : Often associated with other congenital anomalies, such as congenital heart defects, diaphragmatic hernias , and other anomalies of the lung or chest wall.</p>\n<p><strong>Extraedge:</strong></p><p>Pulmonary Sequestration Intralobar sequestration Extralobar sequestration Proportion 75% 25% Pleural Investment Shares the pleural investment with the normal lung Has its own pleura Venous Drainage Usually into the pulmonary venous system Systemic Venous Drainage Timing of presentation Childhood or adulthood Neonatal Period Clinical presentation Recurrent infections, Cough, or hemoptysis Asymptomatic respiratory distress, cyanosis or infection</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which structure arises from abnormal detachments of primitive foregut and is most often located in the hilum or middle mediastinum?", "options": [{"label": "A", "text": "pulmonary hypoplasia", "correct": false}, {"label": "B", "text": "Atelectasis", "correct": false}, {"label": "C", "text": "Foregut cyst", "correct": true}, {"label": "D", "text": "Pulmonary sequestration", "correct": false}], "correct_answer": "C. Foregut cyst", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Foregut cyst Foregut cysts arise from abnormal detachments of primitive foregut and are most often located in the hilum or middle mediastinum.</p>\n<p><strong>Highyeild:</strong></p><p>Foregut cysts These are congenital lesions that arise from the abnormal detachment of the primitive foregut during embryonic development. Site : Foregut cysts can occur anywhere along the foregut, from the oropharynx to the upper stomach, but are most commonly found in the middle mediastinum . Types : bronchogenic cysts(most common), esophageal duplication cysts, and neurenteric cysts. Symptoms : Foregut cysts are usually asymptomatic But can cause symptoms if they become infected or if they compress adjacent structures such as the trachea or esophagus. Diagnosis : Foregut cysts can be diagnosed using imaging studies such as chest X-rays, CT scans, or MRIs. They can also be confirmed by biopsy or surgical resection. Treatment : Depends on their size, location, and symptoms. Small asymptomatic cysts may not require treatment Large or symptomatic cysts may need to be surgically removed. Prognosis : Generally good after surgical resection, with low rates of recurrence or complications. Anterior Mediastinum Middle Mediastinum Posterior Mediastinum Superior mediastinum 1. Thymoma (Most common in ant mediastinum) 1. Cysts (Most common in middle mediastinum) ● Pericardial ● Bronchogenic ● Neuroenteric ● Heterogeneous 1.Neurogenic tumors ● Neuroblastoma ● Ganglioneuroma ● Paraganglioma 1. Lymphomas 2. Thymic hyperplasia 2. Lymphoma 2. Gastroenteric cysts 2. Thyroid process 3. Parathyroid masses 3. Pheochromocytoma 3. Bronchogenic cysts 4. Germ cell tumors 4. Aneurysms 4. Bochdalek hernia 5. Bronchogenic cyst 5. Mesenchymal tumors 5. Lymphoma 6. Lymphoma 6. Pheochromocytoma 7. Aneurysm, Angiomas</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Pulmonary hypoplasia : This is a condition in which the lungs are underdeveloped or have incomplete growth. It can be caused by a variety of factors such as genetic abnormalities, maternal smoking, or compression of the developing lungs in utero. Option: B. Atelectasis : This is a condition in which the lung or a portion of the lung collapses, leading to decreased oxygenation and potentially respiratory distress. Atelectasis can be caused by a variety of factors such as airway obstruction, anesthesia, or compression of the lung. Option: D. Pulmonary sequestration : This is a rare congenital condition in which a portion of lung tissue is separate from the normal bronchopulmonary tree and is supplied by an anomalous systemic artery. Pulmonary sequestration is typically located in the lower lobes of the lung and can present with recurrent infections or respiratory distress.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statement are true regarding the pathogenesis of acute lung injury?", "options": [{"label": "A", "text": "Endothelial activation is the early event", "correct": false}, {"label": "B", "text": "Adhesion and extravasation of neutrophils occurs", "correct": false}, {"label": "C", "text": "Accumulation of intra-alveolar fluid and formation of hyaline membranes is also seen", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above All of the above statements are true regarding the pathogenesis of acute lung injury.</p>\n<p><strong>Highyeild:</strong></p><p>Acute Respiratory Distress Syndrome ARDS is a severe form of acute lung injury characterized by diffuse alveolar damage, increased permeability of the alveolar-capillary membrane, and severe hypoxemia. -Etiology: sepsis, trauma, aspiration, pneumonia, and pancreatitis. Pathophysiology: It involves a complex interplay between inflammatory mediators, endothelial dysfunction, and alveolar epithelial injury. -Features: Rapid onset of severe dyspnea , Tachypnea, and Hypoxemia . Patients may require mechanical ventilation to maintain Treatment: The mainstay of treatment for ARDS is Supportive care, including mechanical ventilation, fluid management, and nutritional support. Specific interventions such as prone positioning and Extracorporeal membrane oxygenation ( ECMO ) may also be considered in select cases.</p>\n<p><strong>Table:</strong></p><p>Berlin\nDefinition of Adult ARDS Timing Within 1 week of a known Clinical insult or new or worsening\n respiratory symptoms Chest opacities Bilateral opacities- not fully explained by effusions, lobar/lung\n collapse, or nodules Origin of edema Respiratory failure not fully explained by cardiac failure or fluid\n overload Need objective assessment (eg, echocardiography) to exclude\n hydrostatic edema if no risk factor present Grading Mild : 200 mmHg <Pao2 /FIO2≤300 mm Hg\n with PEEP or CPAP 25 cm H20 Moderate : 100 mm Hg < Pao2/FIO2≤200 mm Hg\n with PEEP 25 cm H₂O Severe : Pao/FIO,≤100 mm Hg with PEEP ≥5 cm\n H₂O</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 42-year-old patient was admitted to the hospital with chief complaints of dyspnoea and tachypnoea. Based on the histological picture given below, what is your diagnosis?", "options": [{"label": "A", "text": "Acute lung injury", "correct": true}, {"label": "B", "text": "Asthma", "correct": false}, {"label": "C", "text": "Emphysema", "correct": false}, {"label": "D", "text": "Chronic bronchitis", "correct": false}], "correct_answer": "A. Acute lung injury", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831345078-QTDP100005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Acute lung injury The given clinical history and a histopathological image showing diffuse alveolar damage is suggestive of Acute lung injury.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological findings of ARDS Hyaline membranes : These are pink-staining, proteinaceous deposits that form on the inner surface of the alveoli, and are the hallmark of ARDS. Hyaline membranes are formed due to the accumulation of plasma proteins and cellular debris in the alveoli, resulting in damage to the alveolar-capillary barrier. Inflammation : ARDS is characterized by an inflammatory response in the lungs, which is indicated by the presence of neutrophils and macrophages in the alveoli and interstitial spaces. Edema : The alveolar-capillary barrier in the lungs becomes leaky in ARDS, leading to the accumulation of fluid in the alveoli and interstitial spaces, which is known as pulmonary edema. Alveolar damage : The histopathological features of ARDS include damage to the alveolar walls, leading to the collapse of the alveoli and impaired gas exchange in the lungs. Fibrosis : In some cases of ARDS, there may be the development of fibrosis (scarring) in the lungs, which can lead to long-term respiratory problems.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Asthma: It is a chronic respiratory disease characterized by airway inflammation, narrowing of the airways, and increased mucus production, which can lead to shortness of breath, wheezing, and coughing. Option: C. Emphysema: It is a chronic obstructive pulmonary disease characterized by the destruction of the alveolar walls, leading to reduced gas exchange in the lungs. Option: D. Chronic bronchitis: It is another form of chronic obstructive pulmonary disease characterized by inflammation and narrowing of the airways, leading to cough and increased mucus production.</p>\n<p><strong>Extraedge:</strong></p><p>Phases of Acute lung injury</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Goodpasture syndrome except:", "options": [{"label": "A", "text": "It is a type II hypersensitivity reaction", "correct": false}, {"label": "B", "text": "There is an antibody against the collagen part of the beta 3 chain of collagen VI", "correct": true}, {"label": "C", "text": "Focal alveolar necrosis is seen on HPE", "correct": false}, {"label": "D", "text": "Immunofluorescence shows linear deposits along the basement membranes", "correct": false}], "correct_answer": "B. There is an antibody against the collagen part of the beta 3 chain of collagen VI", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>There is an antibody against the collagen part of the beta 3 chain of collagen VI Goodpasture syndrome is an uncommon autoimmune disease in which kidney and lung injuries are caused by circulating autoantibodies against the noncollagenous domain of the α3 chain of collagen IV.</p>\n<p><strong>Highyeild:</strong></p><p>Goodpasture syndrome Goodpasture syndrome is a rare autoimmune disease that affects the lungs and kidneys. It is aka anti-GBM antibody disease. Cause: Damaged by type II hypersensitivity reaction IgG autoantibodies against the non-collagenous domain of the α3 chain of collagen IV. Age: Bimodal distribution with peak incidence at 20-30 and 60-70 years Risk factors: Genetic predisposition: HLA-DR15 Environmental factors: infection, Smoking, oxidative stress Features: Pulmonary manifestation occurs before renal features Damaged lung alveoli- Cough, hemoptysis, dysphasia Nephritic syndrome Immunofluorescence studies : shows linear deposits along the basement membrane Treatment: Corticosteroids and immunosuppressive therapy</p>\n<p><strong>Extraedge:</strong></p><p>Histopathological Findings of Goodpasture Syndrome There is focal necrosis of alveolar walls associated with intra-alveolar hemorrhages. Often the alveoli contain hemosiderin-laden macrophages. In later stages, there may be fibrous thickening of the septae , hypertrophy of type II pneumocytes, and organization of blood in alveolar spaces. In many cases, immunofluorescence studies reveal linear deposits of immunoglobulins along the basement membranes of the septal walls.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding minimal change disease except:", "options": [{"label": "A", "text": "It is the most common cause of nephrotic syndrome in children", "correct": false}, {"label": "B", "text": "Glomeruli are normal on light microscopy", "correct": false}, {"label": "C", "text": "Electron microscopy shows dense deposits along the GBM", "correct": true}, {"label": "D", "text": "Immunofluorescence study shows the absence of deposits", "correct": false}], "correct_answer": "C. Electron microscopy shows dense deposits along the GBM", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Electron microscopy shows dense deposits along the GBM Electron microscopy shows no significant deposits in minimal change disease. Only effacement of the podocyte foot process is seen.</p>\n<p><strong>Highyeild:</strong></p><p>Minimal change disease Aka lipoid necrosis. A most common cause of nephrotic syndrome in children. Cause: Primary : idiopathic, triggered by infection, immunization, immune stimulus Secondary to lymphoma Diagnosis: Light microscopy: Normal glomeruli aka NIL disease. Immunofluorescence studies show no significant deposits or immune complexes in MCD. Electron microscopy: Effacement of podocyte foot process. Excellent response to glucocorticoids</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A., B., D. All are true</p>\n<p><strong>Extraedge:</strong></p><p>Glomerular diseases associated with nephrotic syndrome Abbreviations: IF , immunofluorescence microscopy; EM , electron microscopy; FPE , foot process effacement</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement\n membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have\n mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II\n (Dense Deposit Disease) C3 deposition in the dense intramembranous\n deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q\n along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3,\n with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Effacement of foot processes can be seen in:", "options": [{"label": "A", "text": "Minimal change in disease", "correct": false}, {"label": "B", "text": "Membranous nephropathy", "correct": false}, {"label": "C", "text": "Diabetic nephropathy", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Effacement of foot processes can be seen in minimal change disease, membranous nephropathy, and diabetic nephropathy .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Minimal change disease (MCD): A kidney disease that causes proteinuria, edema, and low levels of protein in the blood. Effacement of foot processes is a characteristic feature seen in MCD. Option: B. Membranous nephropathy (MN): A glomerular disease that is characterized by the thickening of the glomerular basement membrane due to the deposition of immune complexes. Effacement of foot processes can be seen in some cases of MN. Option: C. Diabetic nephropathy: A kidney disease that affects people with diabetes. It is characterized by damage to the glomeruli, leading to proteinuria, hypertension, and progressive renal failure. Effacement of foot processes is a late finding in diabetic nephropathy and is associated with the development of proteinuria.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The proposed autoantigen in the majority of adult cases of membranous nephropathy is:", "options": [{"label": "A", "text": "Leukotriene C2 receptor", "correct": false}, {"label": "B", "text": "Phospholipase B2 receptor", "correct": false}, {"label": "C", "text": "Phospholipase A2 receptor", "correct": true}, {"label": "D", "text": "Leukotriene D2 receptor", "correct": false}], "correct_answer": "C. Phospholipase A2 receptor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Phospholipase A2 receptor The proposed autoantigen in the majority of adult cases of membranous nephropathy is the phospholipase A2 receptor (PLA2R) , which is located on the podocyte surface. These antibodies are thought to form immune complexes with PLA2R, leading to complement activation and inflammation in the glomerulus.</p>\n<p><strong>Highyeild:</strong></p><p>Membranous nephropathy Aka membranous glomerulonephritis Cause: Primary: Antibodies to phospholipase A2 receptor (PLA2R) Secondary: Drugs (NSAIDS, Penicillamine, gold), Infections (HBV, HCV, Syphilis), SLE, or solid tumors (Colon Cancer, lung cancer) Increased risk of thromboembolism May progress to CKD Diagnosis Light Microscopy: Diffuse capillary and GBM thickening Immunofluorescence studies: Granular due to immune complex deposition Electron Microscopy: Spike and dome appearance of sub-endothelial deposits</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence\n findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have mesangial and\n subepithelial deposits Membranoproliferative Glomerulonephritis Type II (Dense Deposit\n Disease) C3 deposition in the dense intramembranous deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q along the glomerular\n basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3, with different\n patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Nephrotic syndrome disease shows diffused and uniform thickness glomerular capillary wall:", "options": [{"label": "A", "text": "FSGS", "correct": false}, {"label": "B", "text": "Minimal change of disease", "correct": false}, {"label": "C", "text": "MPGN", "correct": false}, {"label": "D", "text": "Membranous nephropathy", "correct": true}], "correct_answer": "D. Membranous nephropathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Membranous nephropathy The nephrotic syndrome disease that shows the diffuse and uniform thickness of the glomerular capillary wall is membranous nephropathy.</p>\n<p><strong>Highyeild:</strong></p><p>Membranous nephropathy Aka membranous glomerulonephritis Cause: Primary: Antibodies to phospholipase A2 receptor (PLA2R) Secondary: Drugs (NSAIDS, Penicillamine, gold), Infections (HBV, HCV, Syphilis), SLE, or solid tumors (Colon Cancer, lung cancer) Increased risk of thromboembolism May progress to CKD Diagnosis Light Microscopy: Diffuse capillary and GBM thickening Immunofluorescence studies: Granular due to immune complex deposition Electron Microscopy: Spike and dome appearance of sub-endothelial deposits</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. FSGS : It (focal segmental glomerulosclerosis) is a nephrotic syndrome disease that is characterized by focal and segmental glomerular scarring. On renal biopsy, FSGS typically shows areas of sclerosis affecting some but not all glomeruli, whereas others remain normal. Option: B. Minimal change disease : It (MCD) is a nephrotic syndrome disease that typically shows normal glomeruli on light microscopy, without any significant changes or abnormalities. Option: C. MPGN : It (membranoproliferative glomerulonephritis) is a nephrotic syndrome disease that is characterized by mesangial hypercellularity and proliferation, as well as thickening of the glomerular capillary wall.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II (Dense Deposit Disease) C3 deposition in the dense intramembranous deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3, with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding membranous nephropathy except:", "options": [{"label": "A", "text": "Histological show diffuse thickening of the glomerular capillary wall", "correct": false}, {"label": "B", "text": "Immune complex deposits are seen on the subendothelial region", "correct": true}, {"label": "C", "text": "Electron microscopy shows spikes", "correct": false}, {"label": "D", "text": "Immunofluorescence study shows granular deposits of IgG", "correct": false}], "correct_answer": "B. Immune complex deposits are seen on the subendothelial region", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Immune complex deposits are seen on the subendothelial region Immune complex deposits in membranous nephropathy are typically seen in the subepithelial region , not in the subendothelial region.</p>\n<p><strong>Highyeild:</strong></p><p>Membranous nephropathy Aka membranous glomerulonephritis Cause: Primary: Antibodies to phospholipase A2 receptor (PLA2R) Secondary: Drugs (NSAIDS, Penicillamine, gold), Infections (HBV, HCV, Syphilis), SLE, or solid tumors (Colon Cancer, lung cancer) Increased risk of thromboembolism May progress to CKD Diagnosis Light Microscopy: Diffuse capillary and GBM thickening Immunofluorescence studies: Granular due to immune complex deposition Electron Microscopy: Spike and dome appearance of sub-endothelial deposits</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II (Dense Deposit Disease) C3 deposition in the dense intramembranous deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3, with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old patient presented with hematuria, pitted edema, mild hypertension, and lipiduria. Renal biopsy shows characteristic histological features. So based on the clinical histological findings what is your diagnosis?", "options": [{"label": "A", "text": "Membranous nephropathy", "correct": true}, {"label": "B", "text": "Minimal change of disease", "correct": false}, {"label": "C", "text": "FSGS", "correct": false}, {"label": "D", "text": "MPGN", "correct": false}], "correct_answer": "A. Membranous nephropathy", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1697194843264-QTDP141004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Membranous nephropathy The given clinical scenario with histological findings of diffuse capillary and EGM thickening suggests the diagnosis of Membranous nephropathy.</p>\n<p><strong>Highyeild:</strong></p><p>Membranous nephropathy Aka membranous glomerulonephritis Cause: Primary: Antibodies to phospholipase A2 receptor (PLA2R) Secondary: Drugs (NSAIDS, Penicillamine, gold), Infections (HBV, HCV, Syphilis), SLE, or solid tumors (Colon Cancer, lung cancer) Increased risk of thromboembolism May progress to CKD Diagnosis Light Microscopy: Diffuse capillary and GBM thickening Immunofluorescence studies: Granular due to immune complex deposition Electron Microscopy: Spike and dome appearance of sub-endothelial deposits</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:B. Minimal change disease: It typically presents with diffuse podocyte foot process effacement on electron microscopy, rather than capillary and EGM thickening. Option:C. FSGS: It typically presents with focal segmental glomerulosclerosis and/or mesangial expansion on histology, and the patient would be more likely to have significant proteinuria rather than hematuria Option:D. MPGN: It is more commonly associated with mesangial cell proliferation, double contours of the GBM, and/or subendothelial deposits on histology.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II (Dense Deposit Disease) C3 deposition in the dense intramembranous deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3, with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding MPGN type 1 except:", "options": [{"label": "A", "text": "Histological there is the proliferation of mesangial cells along with the endocapillary proliferation", "correct": false}, {"label": "B", "text": "Immunofluorescence study shows mesangial deposits of IgG and C-3", "correct": false}, {"label": "C", "text": "Electron microscopy shows show dense subendothelial deposits", "correct": false}, {"label": "D", "text": "Spikes are seen on silver stain", "correct": true}], "correct_answer": "D. Spikes are seen on silver stain", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Spikes are seen on silver stain Spikes are not seen on the silver stain in MPGN type 1. MPGN type 1 is a type of glomerulonephritis characterized by mesangial cell proliferation and endocapillary proliferation. Electron microscopy shows dense subendothelial deposits, which give a tram-track appearance. On silver stain, there is a granular deposition of material, but spikes are not seen.</p>\n<p><strong>Highyeild:</strong></p><p>Membranoproliferative glomerulonephritis (MPGN) It is a nephritic syndrome that often co-presents with nephrotic syndrome. Types: Characteristics Type 1 MPGN Type 2 MPGN Associated condition Hepatitis B and C, cryoglobulinemia C3 glomerulopathy Depositis Subendothelial Intramembranous Immunofluorescence IgG, C3 C3 Electron microscopy Large, electron-dense, \"tram-track\" deposits Smaller, electron-lucent, ribbon-like In both types: Mesangial in growth leads to GBM splitting giving a “ tram-track appearance” on H&E and PAS stain</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "C-3 nephritic factor is associated with:", "options": [{"label": "A", "text": "MPGN Type 1", "correct": false}, {"label": "B", "text": "MPGN Type 2", "correct": true}, {"label": "C", "text": "Membranous nephropathy", "correct": false}, {"label": "D", "text": "Minimal change of disease", "correct": false}], "correct_answer": "B. MPGN Type 2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MPGN Type 2 C3 nephritic factor is associated with MPGN Type 2 , which is also known as dense deposit disease.</p>\n<p><strong>Highyeild:</strong></p><p>Membranoproliferative glomerulonephritis (MPGN) It is a nephritic syndrome that often co-presents with nephrotic syndrome. Types: Characteristics Type 1 MPGN Type 2 MPGN Associated condition Hepatitis B and C, cryoglobulinemia C3 glomerulopathy Depositis Subendothelial Intramembranous Immunofluorescence IgG, C3 C3 Electron microscopy Large, electron-dense, \"tram-track\" deposits Smaller, electron-lucent, ribbon-like In both types: Mesangial in growth leads to GBM splitting giving a “ tram-track appearance” on H&E and PAS stain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. MPGN Type 1: It is not associated with C3 nephritic factor. It is caused by the deposition of immune complexes in the glomerulus. Option: C. Membranous nephropathy: It is caused by the deposition of immune complexes in the subepithelial space of the glomerulus. Option: D. Minimal change disease: It is not associated with C3 nephritic factor. It is a type of nephrotic syndrome that is characterized by diffuse effacement of podocyte foot processes without any significant deposition of immunoglobulin or complement.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old male with a history of hepatitis C infection presents with proteinuria, hematuria, and elevated serum creatinine. A renal biopsy is performed, and the image of the same is shown below. What is the most likely diagnosis?", "options": [{"label": "A", "text": "FSGS", "correct": false}, {"label": "B", "text": "Membranous nephropathy", "correct": false}, {"label": "C", "text": "MPGN", "correct": true}, {"label": "D", "text": "Crescentic glomerulonephritis", "correct": false}], "correct_answer": "C. MPGN", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MPGN The given clinical history and history theological image showing “ tram-track appearance ” suggests the diagnosis of mesangioproliferative glomerulonephritis (MPGN).</p>\n<p><strong>Highyeild:</strong></p><p>Membranoproliferative glomerulonephritis (MPGN) It is a nephritic syndrome that often co-presents with nephrotic syndrome. Types: Characteristics Type 1 MPGN Type 2 MPGN Associated condition Hepatitis B and C, cryoglobulinemia C3 glomerulopathy Depositis Subendothelial Intramembranous Immunofluorescence IgG, C3 C3 Electron microscopy Large, electron-dense, \"tram-track\" deposits Smaller, electron-lucent, ribbon-like In both types: Mesangial in growth leads to GBM splitting giving a “ tram-track appearance” on H&E and PAS stain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. FSGS: It is characterized by the focal and segmental scarring of the glomeruli, leading to the collapse of affected glomeruli and the development of hyalinosis. Option: B. Membranous nephropathy: It is a type of glomerulonephritis characterized by the thickening of the glomerular basement membrane (GBM) and the presence of immune complex deposits. Option: D. RPGN: It is characterized by the formation of crescent-shaped structures in the glomeruli, which are made up of fibrin, immune cells, proliferating parietal cells, and other components.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a patient with kidney disease, the presence of a 'tram track appearance' on renal histology is indicative of which specific renal condition?", "options": [{"label": "A", "text": "MPGN type 1", "correct": true}, {"label": "B", "text": "MGN", "correct": false}, {"label": "C", "text": "Lupus nephritis", "correct": false}, {"label": "D", "text": "C3NEF disease", "correct": false}], "correct_answer": "A. MPGN type 1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MPGN type 1 MPGN type 1 is characterized by the deposition of both immune complexes (usually containing IgG and C3) and complement components within the glomerular basement membrane. The classic histological finding in MPGN type 1 is a tram track appearance , which refers to a double contour or duplication of the glomerular basement membrane , seen on light microscopy. In immunofluorescence (IF) staining, MPGN type 1 typically shows both IgG and C3 deposits.</p>\n<p><strong>Highyeild:</strong></p><p>Membranoproliferative glomerulonephritis (MPGN) It is a nephritic syndrome that often co-presents with nephrotic syndrome. Types: Characteristics Type 1 MPGN Type 2 MPGN Associated condition Hepatitis B and C, cryoglobulinemia C3 glomerulopathy Depositis Subendothelial Intramembranous Immunofluorescence IgG, C3 C3 Electron microscopy Large, electron-dense, \"tram-track\" deposits Smaller, electron-lucent, ribbon-like In both types: Mesangial in growth leads to GBM splitting giving “ tram-track appearance” on H&E and PAS stain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Membranous glomerulonephritis is characterized by the deposition of immune complexes primarily composed of IgG along the glomerular basement membrane. The histological finding in MGN is the thickening of the glomerular basement membrane but without the tram track appearance. Option: C. Lupus nephritis is a kidney inflammation caused by systemic lupus erythematosus (SLE). Lupus nephritis can present with various histological patterns, including mesangial proliferation, membranous nephropathy, and focal segmental glomerulonephritis. IF staining in lupus nephritis can show various patterns of immune complex deposition, including IgG and complement (C3) deposits. Option: D. C3NEF disease is a rare autoimmune disorder characterized by the presence of C3 nephritic factor (C3NEF), an autoantibody that stabilizes and activates the alternative complement pathway. In C3NEF disease, there is uncontrolled complement activation leading to consumption of C3, resulting in low serum C3 levels.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which cell-derived chemical mediators of inflammation are not performed in secretory granules?", "options": [{"label": "A", "text": "Histamine", "correct": false}, {"label": "B", "text": "Lysosomal enzymes", "correct": false}, {"label": "C", "text": "Leukotrienes", "correct": true}, {"label": "D", "text": "Myeloperoxidase", "correct": false}], "correct_answer": "C. Leukotrienes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leukotrienes Mediators are either secreted by cells or generated from plasma proteins . Cell-derived mediators are normally sequestered in intracellular granules . They can be rapidly secreted by granule exocytosis (g., histamine in mast cell granules) or synthesised de novo (e.g., prostaglandins, leukotrienes, and cytokines) in response to a stimulus. Leukotrienes are produced in leukocytes and mast cells by the action of lipoxygenase and are involved in vascular and smooth muscle reactions and leukocyte recruitment, synthesised de novo . Mediators of inflammation: Cell-derived Preformed Histamine Serotonin Primary and secondary granules of neutrophils Synthesised de novo NO Platelet-activating factor (PAF) Arachidonic acid metabolite ( Leukotrienes and Prostaglandins) Interleukins/Cytokines Plasma-derived Complements Kinins Coagulation factors</p>\n<p><strong>Highyeild:</strong></p><p>Source of inflammatory mediators: Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Histamine. Preformed mediator . Option: B. Lysosomal enzymes. Preformed mediator . Option: D. Myeloperoxidase. Primary granules in neutrophil . Preformed mediator .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is an Opsonin?", "options": [{"label": "A", "text": "C3a", "correct": false}, {"label": "B", "text": "C3b", "correct": true}, {"label": "C", "text": "C5a", "correct": false}, {"label": "D", "text": "LTC4", "correct": false}], "correct_answer": "B. C3b", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C3b Opsonisation and phagocytosis: C3b and its cleavage product iC3b (inactive C3b), when fixed to a microbial cell wall, act as opsonins and promote phagocytosis by neutrophils and macrophages , which bear cell surface receptors for the complement fragments. Phagocytosis efficiency is greatly enhanced when microbes are coated with opsonins for which the phagocytes express high-affinity receptors. The major opsonins are: IgM and Fc receptors of IgG C3b breakdown product of complement ( C3a, C4b, C5b ) Mannose-binding lectin Fibrinogen C- Reactive Protein ( CRP )</p>\n<p><strong>Highyeild:</strong></p><p>Role of inflammatory mediators: table,tr,th,td {border:1px solid black;} Reaction of Inflammation Principal Mediators Vasodilation Histamine Prostaglandins Increased vascular permeability Histamine and serotonin C3a and C5a (by liberating vasoactive amines from mast cells, other cells) Leukotrienes C4, D4, E4 Chemotaxis, leukocyte recruitment and activation TNF, IL-I Chemokines C3a, C5a Leukotriene B4 Fever IL-1, TNF Prostaglandins Pain Prostaglandins Bradykinin Substance P Tissue damage Lysosomal enzymes of leukocytes Reactive oxygen species Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE,, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. C3a. Anaphylatoxin . Option: B. C5a. Chemotactic agent for neutrophils, monocytes, eosinophils, basophils, and Anaphylatoxin . Option: C. LTC4. Leukotriene C4 Intense vasoconstriction, bronchospasm (important in asthma) , and increased permeability of venules.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following complement is a chemokine as well as anaphylatoxin?", "options": [{"label": "A", "text": "C3a", "correct": false}, {"label": "B", "text": "C3b", "correct": false}, {"label": "C", "text": "C5a", "correct": true}, {"label": "D", "text": "C5b", "correct": false}], "correct_answer": "C. C5a", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C5a C5a , C3a, and, to a lesser extent, C4a are cleavage products of the corresponding complement components that stimulate histamine release from mast cells and thereby increase vascular permeability and cause vasodilation . C5a is also a chemotactic agent for neutrophils, monocytes, eosinophils, and basophils. C5a is both a Chemokine and Anaphylatoxin .</p>\n<p><strong>Highyeild:</strong></p><p>Role of inflammatory mediators: table,tr,th,td {border:1px solid black;} Reaction of Inflammation Principal Mediators Vasodilation Histamine Prostaglandins Increased vascular permeability Histamine and serotonin C3a and C5a (by liberating vasoactive amines from mast cells, other cells) Leukotrienes C4, D4, E4 Chemotaxis, leukocyte recruitment and activation TNF, IL-I Chemokines C3a, C5a Leukotriene B4 Fever IL-1, TNF Prostaglandins Pain Prostaglandins Bradykinin Substance P Tissue damage Lysosomal enzymes of leukocytes Reactive oxygen species Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE,, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. C3a. It is an anaphylatoxin only , not a chemokine. Option: C3b. Opsonin . Op tion: D. C5b. Opsonin .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the function of bradykinin?", "options": [{"label": "A", "text": "Increased vascular permeability", "correct": false}, {"label": "B", "text": "Pain", "correct": false}, {"label": "C", "text": "Vasodilation", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Bradykinin increases vascular permeability and causes contraction of smooth muscle, dilation of blood vessels, and pain when injected into the skin . These effects are similar to those of histamine. The action of bradykinin is short-lived because it is quickly inactivated by an enzyme called kininase .</p>\n<p><strong>Highyeild:</strong></p><p>Role of inflammatory mediators: table,tr,th,td {border:1px solid black;} Reaction of Inflammation Principal Mediators Vasodilation Histamine Prostaglandins Increased vascular permeability Histamine and serotonin C3a and C5a (by liberating vasoactive amines from mast cells, other cells) Leukotrienes C4, D4, E4 Chemotaxis, leukocyte recruitment and activation TNF, IL-I Chemokines C3a, C5a Leukotriene B4 Fever IL-1, TNF Prostaglandins Pain Prostaglandins Bradykinin Substance P Tissue damage Lysosomal enzymes of leukocytes Reactive oxygen species Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE,, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Increased vascular permeability. True . Option: B. Pain. True . Option: C. Vasodilation. True</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is true regarding bradykinin?", "options": [{"label": "A", "text": "Kininogen converts kallikrein to kinin", "correct": false}, {"label": "B", "text": "Bradykinin increases skeletal muscle contraction", "correct": false}, {"label": "C", "text": "Its effects are similar to serotonin", "correct": false}, {"label": "D", "text": "Its action is short-lived", "correct": true}], "correct_answer": "D. Its action is short-lived", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Its action is short-lived The action of bradykinin is short-lived because it is quickly inactivated by an enzyme called kininase. Bradykinin has been implicated as a mediator in some forms of allergic reactions, such as anaphylaxis.</p>\n<p><strong>Highyeild:</strong></p><p>Role of inflammatory mediators: table,tr,th,td {border:1px solid black;} Reaction of Inflammation Principal Mediators Vasodilation Histamine Prostaglandins Increased vascular permeability Histamine and serotonin C3a and C5a (by liberating vasoactive amines from mast cells, other cells) Leukotrienes C4, D4, E4 Chemotaxis, leukocyte recruitment and activation TNF, IL-I Chemokines C3a, C5a Leukotriene B4 Fever IL-1, TNF Prostaglandins Pain Prostaglandins Bradykinin Substance P Tissue damage Lysosomal enzymes of leukocytes Reactive oxygen species Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE,, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Kininogen converts kallikrein to kinin. Kinins are vasoactive peptides derived from plasma proteins , called kininogens , by the action of specific proteases called kallikrein . The enzyme kallikrein cleaves a plasma glycoprotein precursor, high-molecular-weight kininogen, to produce bradykinin . Option: B. Bradykinin increases skeletal muscle contraction. Bradykinin increases vascular permeability and causes the contraction of smooth muscle Option: C. Its effects are similar to serotonin. The effects are similar to those of histamine . Serotonin (5-hydroxytryptamine) is a preformed vasoactive mediator in platelets and specific neuroendocrine cells, such as the gastrointestinal tract.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Histamine and serotonin are secreted by the following cells, respectively?", "options": [{"label": "A", "text": "Platelets, Enterochromaffin cells", "correct": false}, {"label": "B", "text": "Enterochromaffin cells, Endothelium", "correct": false}, {"label": "C", "text": "Mast cells, Enterochromaffin cells", "correct": true}, {"label": "D", "text": "Mast cells, Endothelium", "correct": false}], "correct_answer": "C. Mast cells, Enterochromaffin cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mast cells, Enterochromaffin cells The two primary vasoactive amines , so named because they have important actions on blood vessels, are histamine and serotonin . The richest source of histamine in mast cells is generally present in the connective tissue adjacent to blood vessels and in basophils and platelets. Serotonin (5-hydroxytryptamine) is a preformed vasoactive mediator in platelets and specific neuroendocrine cells, such as the gastrointestinal tract .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Platelets, Enterochromaffin cells. Incorrect . Option: B. Enterochromaffin cells, Endothelium. Incorrect . Option: D. Mast cells, Endothelium. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Nitric oxide is synthesised by -", "options": [{"label": "A", "text": "Citrulline", "correct": false}, {"label": "B", "text": "Asparagine", "correct": false}, {"label": "C", "text": "Arginine", "correct": true}, {"label": "D", "text": "Ornithine", "correct": false}], "correct_answer": "C. Arginine", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Arginine NO , a soluble gas produced from arginine by the action of nitric oxide synthase (NOS) , also participates in microbial killing. In addition to its role as a microbicidal substance, NO relaxes vascular smooth muscle and promotes vasodilation.</p>\n<p><strong>Highyeild:</strong></p><p>NO is synthesised from Arginine . Sites: Endothelium (eNO): Maintains vascular tone Nerves (nNO): Neurotransmitter Inducible (iNO): Inflammation Functions: Vasodilation Smooth muscle relaxation Reactive Oxygen Species</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Citrulline. Using nitric oxide synthase, arginine converts Arginine into Citrulline and releases NO. Option: Asparagine. Incorrect . Option: D. Ornithine. Incorrect option.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a function of NO?", "options": [{"label": "A", "text": "Vasodilation", "correct": false}, {"label": "B", "text": "Neurotransmission", "correct": false}, {"label": "C", "text": "Decrease platelets aggregation", "correct": false}, {"label": "D", "text": "None of the above", "correct": true}], "correct_answer": "D. None of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above NO , a soluble gas produced from arginine by the action of nitric oxide synthase (NOS) , also participates in microbial killing. In addition to its role as a microbicidal substance, NO relaxes vascular smooth muscle and promotes vasodilation.</p>\n<p><strong>Highyeild:</strong></p><p>NO is synthesised from Arginine . Sites: Endothelium (eNO): Maintains vascular tone Nerves (nNO): Neurotransmitter Inducible (iNO): Inflammation Functions: Vasodilation Smooth muscle relaxation Reactive Oxygen Species</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Vasodilation. True . Option: B. Neurotransmission. True . Option: C. Decrease platelet aggregation. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding Platelet Activating Factor?", "options": [{"label": "A", "text": "It causes vasodilation at high concentrations", "correct": false}, {"label": "B", "text": "It is released by platelets only", "correct": false}, {"label": "C", "text": "At low concentrations, it causes vasoconstriction", "correct": false}, {"label": "D", "text": "It can also cause bronchoconstriction", "correct": true}], "correct_answer": "D. It can also cause bronchoconstriction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It can also cause bronchoconstriction Platelet-activating factor (PAF) is a phospholipid-derived mediator. In addition to platelet aggregation , PAF causes vasoconstriction and bronchoconstriction , and at low concentrations, it induces vasodilation and increased venular permeability .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: It causes vasodilation at high concentrations. It causes vasodilation and increased venular permeability at low concentrations . Option: B . It is released by platelets only. Cell types, including platelets, basophils, mast cells, neutrophils, macrophages, and endothelial cells , can elaborate PAF in both secreted and cell-bound forms. Option: C . At low concentrations, it causes vasoconstriction. It causes vasoconstriction and platelet aggregation at high concentrations .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What are the mediators formed by the Cyclooxygenase pathway, named a,b, and c respectively given in the Image given below?", "options": [{"label": "A", "text": "PGD2, PGI2, PAGE2", "correct": false}, {"label": "B", "text": "PGD2, PAGE2, PGI2", "correct": false}, {"label": "C", "text": "TXA2, PGI2, PGD2", "correct": false}, {"label": "D", "text": "PGI2, TXA2, PGD2", "correct": true}], "correct_answer": "D. PGI2, TXA2, PGD2", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1742890648445-photos-1686815707449-QTDP019014IMG1(2).png"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PGI2, TXA2, PGD2 Platelets contain the enzyme thromboxane synthase , and hence TxA2 is the major product in these cells. TxA2 , a potent platelet-aggregating agent and vasoconstrictor , is unstable and rapidly converted to an inactive form. The vascular endothelium lacks thromboxane synthase but contains prostacyclin synthase , which is responsible for the formation of prostacyclin (PGI2) and its stable end product PGF1a. Prostacyclin is a vasodilator and a potent inhibitor of platelet aggregation and also markedly potentiates the permeability-increasing and chemotactic effects of other mediators. PGD2 is the major prostaglandin made by mast cells ; along with PAGE2, it causes vasodilation and increases the permeability of postcapillary venules, thus potentiating edema formation . PGD2 also is a chemoattractant for neutrophils .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, B, D are incorrect</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: table,tr,th,td {border:1px solid black;} Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following leukotrienes cause vasoconstriction except?", "options": [{"label": "A", "text": "LTB4", "correct": true}, {"label": "B", "text": "LTC4", "correct": false}, {"label": "C", "text": "LTD4", "correct": false}, {"label": "D", "text": "LTE4", "correct": false}], "correct_answer": "A. LTB4", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>LTB4 LTB 4 is a potent chemotactic agent and activator of neutrophils , causing aggregation and adhesion of the cells to venular endothelium , generation of ROS , and release of lysosomal enzymes . The cysteinyl-containing leukotrienes LTC4, LTD4, and LTE 4 cause intense vasoconstriction, bronchospasm (important in asthma), and increased permeability of venules. table,tr,th,td {border:1px solid black;} Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, B, C are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following increases platelet aggregation?", "options": [{"label": "A", "text": "PGD2", "correct": false}, {"label": "B", "text": "PAGE2", "correct": false}, {"label": "C", "text": "PGI2", "correct": false}, {"label": "D", "text": "TXA2", "correct": true}], "correct_answer": "D. TXA2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TXA2 Platelets contain the enzyme thromboxane synthase , and hence TxA2 is the primary product in these cells. TxA2 , a potent platelet-aggregating agent and vasoconstrictor , is unstable and rapidly converted to an inactive form. The vascular endothelium lacks thromboxane synthase but contains prostacyclin synthase , which is responsible for the formation of prostacyclin (PGI2) and its stable end product PGF1a. Prostacyclin is a vasodilator and a potent inhibitor of platelet aggregation and also markedly potentiates the permeability-increasing and chemotactic effects of other mediators. PGD2 is the major prostaglandin made by mast cells ; along with PAGE2 , it causes vasodilation and increases the permeability of postcapillary venules, thus potentiating edema formation . PGD2 also is a chemoattractant for neutrophils .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. PGD2. Increase mucin production . Option: B. PAGE2 Causes vasodilation . Option: C. PGI2. Decrease platelet aggregation .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Table 3.6 Principal Actions of Arachidonic Acid Metabolites in Inflammation Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the main cytokines during the acute inflammatory response?", "options": [{"label": "A", "text": "TNF", "correct": true}, {"label": "B", "text": "IFN- gamma", "correct": false}, {"label": "C", "text": "TGF- beta", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "A. TNF", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TNF TNF and IL-1 serve critical roles in leukocyte recruitment by promoting the adhesion of leukocytes to endothelium and their migration through blood vessels . Microbial products, dead cells, immune complexes, foreign bodies, physical injury, and other inflammatory stimuli can stimulate the secretion of TNF and IL-1.</p>\n<p><strong>Highyeild:</strong></p><p>Cytokine Principal Sources Principal Actions in Inflammation In Acute Inflammation TNF Macrophages, mast cells, T lymphocytes Stimulates expression of endothelial adhesion molecules and secretion of other cytokines; systemic effects IL-I Macrophages, endothelial cells, some epithelial cells Similar to TNF; greater role in fever IL-6 Macrophages, other cells Systemic effects (acute phase response) Chemokines Macrophages, endothelial cells, T lymphocytes, mast cells, other cell types Recruitment of leukocytes to sites of inflammation; migration of cells in normal tissues IL-17 T lymphocytes Recruitment of neutrophils and monocytes In Chronic Inflammation IL-12 Dendritic cells, macrophages Increased production of IFN-y IFN-Y T lymphocytes, NK cells Activation of macrophages (increased ability to kill microbes and tumor cells) IL-17 T lymphocytes Recruitment of neutrophils and monocytes</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. IFN- gamma. Mostly in chronic Inflammation . Option: C. TGF- beta. Involved in the healing process . Option: D. All of the above. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are the effects of cytokines during inflammation except?", "options": [{"label": "A", "text": "Production of acute phase reactants", "correct": false}, {"label": "B", "text": "Fever and cachexia", "correct": false}, {"label": "C", "text": "Stimulate endothelium and macrophages", "correct": false}, {"label": "D", "text": "None of the above", "correct": true}], "correct_answer": "D. None of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>None of the above Cytokines are proteins produced by many cell types (principally activated lymphocytes, macrophages, and dendritic cells, but also endothelial, epithelial, and connective tissue cells) that mediate and regulate immune and inflammatory reactions .</p>\n<p><strong>Highyeild:</strong></p><p>Cytokine Principal Sources Principal Actions in Inflammation In Acute Inflammation TNF Macrophages, mast cells, T lymphocytes Stimulates expression of endothelial adhesion molecules and secretion of other cytokines; systemic effects IL-I Macrophages, endothelial cells, some epithelial cells Similar to TNF; greater role in fever IL-6 Macrophages, other cells Systemic effects (acute phase response) Chemokines Macrophages, endothelial cells, T lymphocytes, mast cells, other cell types Recruitment of leukocytes to sites of inflammation; migration of cells in normal tissues IL-17 T lymphocytes Recruitment of neutrophils and monocytes In Chronic Inflammation IL-12 Dendritic cells, macrophages Increased production of IFN-y IFN-Y T lymphocytes, NK cells Activation of macrophages (increased ability to kill microbes and tumor cells) IL-17 T lymphocytes Recruitment of neutrophils and monocytes</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Production of acute phase reactants. The function of cytokine . Option: B. Fever and cachexia. The function of cytokine . Option: C. Stimulate endothelium and macrophages. The function of cytokine .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following decreases during inflammation?", "options": [{"label": "A", "text": "Fibrinogen", "correct": false}, {"label": "B", "text": "Albumin", "correct": true}, {"label": "C", "text": "CRP", "correct": false}, {"label": "D", "text": "SAA", "correct": false}], "correct_answer": "B. Albumin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Albumin Negative Acute Phase Reactants decrease during inflammation. Albumin and transferrin are negative acute-phase reactants Elevated levels of acute-phase proteins (APR) , which are plasma proteins mostly synthesised in the liver , whose plasma concentrations may increase several hundred–fold as part of the response to inflammatory stimuli.</p>\n<p><strong>Highyeild:</strong></p><p>Acute Phase Reactants: Positive Acute Phase Reactants Negative Acute Phase Reactants Fibrinogen Transferrin CRP Albumin Ferritin Transthyretin Haptoglobin Hepcidin Ceruloplasmin Serum amyloid (SAA)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Fibrinogen. Positive APR . Option: C. CRP. Positive APR . Option: D. SAA. Positive APR .</p>\n<p><strong>Extraedge:</strong></p><p>Elevated serum levels of CRP have been proposed as a marker for increased risk of myocardial infarction in patients with coronary artery disease. It is postulated that inflammation involving atherosclerotic plaques in the coronary arteries may predispose to thrombosis and subsequent infarction. Hepcidin is a small protein that reduces iron availability to erythroid progenitors in the bone marrow; over time, this effect may lead to anemia or chronic inflammation . Thrombopoietin , the major growth factor for megakaryocytes (platelet precursors) in the bone marrow, is also upregulated. As a result, systemic inflammation may be associated with an elevated platelet count ( thrombocytosis ). Acute-phase proteins have beneficial effects during acute inflammation, but prolonged production of these proteins (especially SAA ) in states of chronic inflammation causes secondary amyloidosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are positive acute phase reactants except?", "options": [{"label": "A", "text": "Transferrin", "correct": true}, {"label": "B", "text": "Haptoglobin", "correct": false}, {"label": "C", "text": "Ferritin", "correct": false}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "A. Transferrin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Transferrin It is a negative acute phase reactant .</p>\n<p><strong>Highyeild:</strong></p><p>Acute Phase Reactants: Positive Acute Phase Reactants Negative Acute Phase Reactants Fibrinogen Transferrin CRP Albumin Ferritin Transthyretin Haptoglobin Hepcidin Ceruloplasmin Serum amyloid (SAA) </table</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Haptoglobin. Positive APR . Option: C. Ferritin. Positive APR . Option: D. None. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Elevated serum levels of CRP have been proposed as a marker for increased risk of myocardial infarction in patients with coronary artery disease. It is postulated that inflammation involving atherosclerotic plaques in the coronary arteries may predispose to thrombosis and subsequent infarction. Hepcidin is a small protein that reduces the availability of iron to erythroid progenitors in the bone marrow; over time, this effect may lead to anemia or chronic inflammation . Thrombopoietin , the major growth factor for megakaryocytes (platelet precursors) in the bone marrow, is also upregulated and as a result systemic inflammation may be associated with an elevated platelet count ( thrombocytosis ). Acute-phase proteins have beneficial effects during acute inflammation, but prolonged production of these proteins (especially SAA ) in states of chronic inflammation causes secondary amyloidosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which one of the following is a function of PGI2?", "options": [{"label": "A", "text": "Vasoconstriction and inhibits platelet aggregation", "correct": false}, {"label": "B", "text": "Vasodilator and inhibits platelet aggregation", "correct": true}, {"label": "C", "text": "Vasoconstriction and increases platelet aggregation", "correct": false}, {"label": "D", "text": "Vasodilator and increases platelet aggregation", "correct": false}], "correct_answer": "B. Vasodilator and inhibits platelet aggregation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Vasodilator and inhibits platelet aggregation Platelets contain the enzyme thromboxane synthase , and hence TxA2 is the major product in these cells. TxA2 , a potent platelet-aggregating agent and vasoconstrictor , is itself unstable and rapidly converted to its inactive form. The vascular endothelium lacks thromboxane synthase but contains prostacyclin synthase , which is responsible for the formation of prostacyclin (PGI2) and its stable end product PGF1a. Prostacyclin is a vasodilator and a potent inhibitor of platelet aggregation , and also markedly potentiates the permeability-increasing and chemotactic effects of other mediators. PGD2 is the major prostaglandin made by mast cells ; along with PAGE2 , it causes vasodilation and increases the permeability of postcapillary venules, thus potentiating edema formation . PGD2 also is a chemoattractant for neutrophils .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Vasoconstriction and inhibits platelet aggregation. Incorrect . Option: B. Vasoconstriction and increases platelet aggregation. Incorrect . Option: C. Vasodilator and increases platelet aggregation. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites Table 3.6 Principal Actions of Arachidonic Acid Metabolites in Inflammation Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid. Prostaglandins in platelet homeostasis Thromboxane A2 is produced by COX-1 in activated platelets It promotes adherence and aggregation of circulating platelets along with vascular smooth muscle contraction, therefore promoting blood clot (thrombi) formation Prostacyclin (PGI) is produced by COX-2 in vascular endothelial cells It inhibits platelet aggregation and stimulates vasodilation, and thus, slows down thrombogenesis The opposing effects if Thromboxane A2 and Prostacyclin limits the formation of thrombi to sites of vascular injury Aspirin Has an antithrombogenic effect.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Prostaglandin causing fever is-", "options": [{"label": "A", "text": "PGF2", "correct": false}, {"label": "B", "text": "PGE2", "correct": true}, {"label": "C", "text": "PGE1", "correct": false}, {"label": "D", "text": "PGT2", "correct": false}], "correct_answer": "B. PGE2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PGE2 Pyrogen s : Substances that cause fever. PGE 2 is hyperalgesic , making the skin hypersensitive to painful stimuli such as intradermal injection of suboptimal concentrations of histamine and bradykinin. It is involved in cytokine-induced fever during infections . In the hypothalamus , the prostaglandins, especially PGE2 , stimulate the production of neurotransmitters that reset the temperature set point at a higher level .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, C, D are incorrect</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding about Arachidonic acid (AA) pathway, except:", "options": [{"label": "A", "text": "Aspirin inhibits the arachidonic acid pathway", "correct": false}, {"label": "B", "text": "Cytosolic Calcium leads to activation of membrane phospholipase A2", "correct": false}, {"label": "C", "text": "Action of phospholipase A2 causes synthesis of arachidonic acid", "correct": false}, {"label": "D", "text": "Leukotrienes C4, D4 cause vasodilation", "correct": true}], "correct_answer": "D. Leukotrienes C4, D4 cause vasodilation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leukotrienes C4, D4 cause vasodilation The lipid mediators prostaglandins and leukotrienes are produced from arachidonic acid (AA) present in membrane phospholipids and stimulate vascular and cellular reactions in acute inflammation. AA is a 20-carbon polyunsaturated fatty acid (5,8,11,14-eicosatetraenoic acid) that is derived from dietary sources or by synthesis from a precursor molecule, the essential fatty acid linoleic acid Cellular phospholipases, mainly phospholipase A2 , release AA from membrane phospholipids . Activation of phospholipase A2 is triggered by an increase in cytosolic Calcium Leukotrienes are produced in leukocytes and mast cells by the action of lipoxygenase. Leukotrienes are more potent than histamine in increasing vascular permeability and causing bronchospasm . Cyclo-oxygenase inhibitors such as Aspirin, Indomethacin inhibit the activity of cyclooxygenase involved in the conversion of AA into prostaglandins . Leukotriene A4, B4 cause chemotaxis. Leukotrienes C4 and D4 cause vasoconstriction and increase vascular permeability.</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Aspirin inhibits the arachidonic acid pathway. Correct . Option: B. Cytosolic Calcium leads to the activation of membrane phospholipase A2. Correct . Option: C. Action of phospholipase A2 causes synthesis of arachidonic acid. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are mediators of inflammation, except", "options": [{"label": "A", "text": "Tumour necrosis factor-α (TNF-α)", "correct": false}, {"label": "B", "text": "Interleukin-1", "correct": false}, {"label": "C", "text": "Myeloperoxidase", "correct": true}, {"label": "D", "text": "Prostaglandins", "correct": false}], "correct_answer": "C. Myeloperoxidase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myeloperoxidase Inflammatory mediators are the substances that initiate and regulate inflammatory reactions . The most important mediators of acute inflammation are vasoactive amines, lipid products ( prostaglandins and leukotrienes ), cytokines (including chemokines ), and products of complement activation . Myeloperoxidase (MPO) is an enzyme present in primary (or azurophilic) granules of the neutrophils and takes part in the formation of reactive oxygen species .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Tumour necrosis factor-α (TNF-α). Inflammatory mediator . Option: B. Interleukin-1. Inflammatory mediator . Option: C. Prostaglandins. Inflammatory mediator .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Vitamin K leads to:", "options": [{"label": "A", "text": "Gamma carboxylation of aspartic acid residues to clotting factor 2,7, 9 and 10", "correct": false}, {"label": "B", "text": "Beta-carboxylation of glutamic acid residues to clotting factor 2,7, 9 and 10", "correct": false}, {"label": "C", "text": "Alpha-carboxylation of aspartic acid residues to clotting factor 2,7, 9 and 10", "correct": false}, {"label": "D", "text": "Gamma carboxylation of glutamic acid residues to clotting factor 2,7, 9 and 10", "correct": true}], "correct_answer": "D. Gamma carboxylation of glutamic acid residues to clotting factor 2,7, 9 and 10", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Gamma carboxylation of glutamic acid residues to clotting factor 2,7, 9 and 10 Vi tamin K is synthesised by gut flora . Deficiency is more commonly seen in neonate s . Act as Cofactor in hepatic carboxylation of procoagulants-factors ll(prothrombin), VIl , IX , and X ; and protein C and protein S . Warfarin inhibits epoxide reductase , thus inhibiting the activity of vitamin K enzymatic reactions that produce γ-carboxylated glutamic acid that use Vitamin K as a cofactor and are antagonised by drugs such as Warfarin (Coumadin), a widely used anticoagulant.</p>\n<p><strong>Highyeild:</strong></p><p>Vitamin Functions Deficiency Syndromes Fat-Soluble Vitamin A A component of visual pigment Maintenance of specialized epithelia Maintenance of resistance to infection Night blindness, xerophthalmia, blindness Squamous metaplasia Vulnerability to infection, particularly measles Vitamin D Facilitates intestinal absorption of calcium and phosphorus and mineralization of bone Rickets in children Osteomalacia in adults Vitamin E Major antioxidant; scavenges free radicals Spinocerebellar degeneration, hemolytic anemia Vitamin K Cofactor in hepatic carboxylation of procoagulants-factors Il (prothrombin), VII, IX, and X and protein C and protein S Bleeding diathesis (Chapter 14) Water-Soluble Vitamin B, (thiamine) As pyrophosphate, is coenzyme in decarboxylation reactions Dry and wet beriberi, Wernicke syndrome, Korsakoff syndrome (Chapter 28) Vitamin B2 (riboflavin) Converted to coenzymes flavin mononucleotide and flavin adenine dinucleotide, cofactors for many enzymes in intermediary metabolism Ariboflavinosis, cheilosis, stomatitis, glossitis, dermatitis, corneal vascularization Niacin Incorporated into nicotinamide adenine dinucleotide (NAD) and NAD phosphate, involved in a variety of redox reactions Pellagra \"three Ds\": dementia, dermatitis, diarrhea Vitamin B6 (pyridoxine) Derivatives serve as coenzymes in many intermediary reactions Cheilosis, glossitis, dermatitis, peripheral neuropathy (Chapter 28) Maintenance of myelinization of spinal cord tracts Vitamin B2 Required for normal folate metabolism and DNA synthesis Megaloblastic pernicious anemia and degeneration of posterolateral spinal cord tracts (Chapter 14) Vitamin C Serves in many oxidation-reduction (redox) reactions and hydroxylation of collagen Scurvy Folate Essential for transfer and use of one-carbon units in DNA synthesis Megaloblastic anemia, neural tube defects (Chapter 14) Pantothenic acid Incorporated in coenzyme A No nonexperimental syndrome recognized Biotin Cofactor in carboxylation reactions No clearly defined clinical syndrome</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Gamma carboxylation of aspartic acid residues to clotting factors 2,7, 9 and 10. Incorrect . Option: B. Beta-carboxylation of glutamic acid residues to clotting factors 2,7, 9 and 10. Incorrect . Option: C. Alpha-carboxylation of aspartic acid residues to clotting factors 2,7, 9 and 10. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Activated protein C inhibit clotting mechanism by inactivating which of the following clotting factors:", "options": [{"label": "A", "text": "Factor Illa and Factor VIlla", "correct": false}, {"label": "B", "text": "Factor VIIla and Factor IXa", "correct": false}, {"label": "C", "text": "Factor Va and Factor VIlla", "correct": true}, {"label": "D", "text": "Factor Va and Factor Vlla", "correct": false}], "correct_answer": "C. Factor Va and Factor VIlla", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor Va and Factor VIlla Protein-C is a vitamin K-dependent protease that requires a cofactor (Protein S) . Activated Protein C/protein S forms a complex that is a potent inhibitor of coagulation factors Va and Factor VIlla . Protein C acts as a Tissue factor pathway inhibitor (TFPI)</p>\n<p><strong>Highyeild:</strong></p><p>Primary (Genetic) Common Factor V mutation: factor V Leiden (Arg to Gln substitution in amino acid residue 506 leading to resistance to activated protein C) Prothrombin mutation (G20210A noncoding sequence variant leading to increased prothrombin levels) Increased levels of factors VIII, IX, XI, or fibrinogen (genetics unknown) Rare Antithrombin III deficiency Protein C deficiency Protein S deficiency Very Rare Fibrinolysis defects Homozygous homocystinuria (deficiency of cystathione B-synthetase) Secondary (Acquired) Strong Risk Factors for Thrombosis Prolonged bed rest or immobilization Myocardial infarction Atrial fibrillation Tissue injury (surgery, fracture, burn) Cancer Prosthetic cardiac valves Disseminated intravascular coagulation Heparin-induced thrombocytopenia Antiphospholipid antibody syndrome Other Risk Factors for Thrombosis Cardiomyopathy Nephrotic syndrome Hyperestrogenic states (pregnancy and postpartum) Oral contraceptive use Sickle cell anemia Smoking</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Factor Illa and Factor VIlla. Incorrect . Option: B. Factor VIIla and Factor IXa. Incorrect . Option: D. Factor Va and Factor Vlla. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "An 80-year-old woman presents with a 4-hour history of fever, shaking chills and disorientation. Her blood pressure is 80/40 mm Hg. Physical Examination shows diffuse purpura on her upper arms and chest. Blood Cultures are positive for Gram-negative organisms. Which of the following cytokines is primarily involved in the pathogenesis of direct vascular injury in this patient with septic shock?", "options": [{"label": "A", "text": "Interferon-γ", "correct": false}, {"label": "B", "text": "Transforming Growth Factor-β (TGF-β)", "correct": false}, {"label": "C", "text": "Platelet-derived growth factor", "correct": false}, {"label": "D", "text": "Tumor necrosis factor-α", "correct": true}], "correct_answer": "D. Tumor necrosis factor-α", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tumor necrosis factor-α Septicemia (bacteremia) denotes the clinical condition in which bacteria are found in the circulation . It can be suspected clinically, but the final diagnosis is made by culturing the organisms from the blood. In sepsis, the large amounts of bacteria and their products in the blood stimulate the production of enormous quantities of several cytokines, notably TNF and IL-1 . High blood levels of cytokines cause various clinical manifestations, such as disseminated intravascular coagulation, hypotensive shock, and metabolic disturbances, including insulin resistance and hyperglycemia . This clinical triad is known as septic shock and is one form of a severe, often fatal disorder referred to as systemic inflammatory response syndrome . In patients with endotoxic shock , lipopolysaccharide released from Gram-negative bacteria stimulates monocytes/macrophages to secrete large quantities of TNF- α .</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Interferon-γ. NK cells and T cells secrete cytokines such as interferon-γ ( IFN-γ ), which activate macrophages to destroy ingested microbes and even tumor cells . Option: B. Transforming Growth Factor-β (TGF-β). Antiinflammatory cytokines, like transforming growth factor-β ( TGF-β ) and IL-10, are released from macrophages and help in tissue repair and fibrosis . Option: C. Platelet-derived growth factor. The growth factors platelet-derived growth factor ( PDGF ) results in increased synthesis of extracellular matrix and cause fibrosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 25-year-old woman developed a sore, red, hot, swollen left knee. She has no history of trauma and no family history of joint disease. Aspirin effectively relieves symptoms of acute inflammation in this patient because it inhibits which of the following enzymes?", "options": [{"label": "A", "text": "Cyclooxygenase", "correct": true}, {"label": "B", "text": "Lipoxygenase", "correct": false}, {"label": "C", "text": "Phospholipase A2", "correct": false}, {"label": "D", "text": "Superoxide dismutase", "correct": false}], "correct_answer": "A. Cyclooxygenase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cyclooxygenase The lipid mediators prostaglandins and leukotrienes are produced from arachidonic acid (AA) in membrane phospholipids. Cellular phospholipases, mainly phospholipase A2 , release AA from membrane phospholipids . An increase in cytosolic Calcium triggers the activation of phospholipase A2 . Leukotrienes are produced in leukocytes and mast cells by lipoxygenase. Leukotrienes are more potent than histamine in increasing vascular permeability and causing bronchospasm . Cyclo-oxygenase inhibitors such as Aspirin, Indomethacin inhibit the activity of cyclooxygenase involved in the conversion of AA into prostaglandins , exerting their potent analgesic and anti-inflammatory effects . Leukotriene A4, B4 cause chemotaxis. Leukotrienes C4 and D4 cause vasoconstriction and increase vascular permeability.</p>\n<p><strong>Highyeild:</strong></p><p>Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Lipoxygenase. Inhibited by Zileuton . Option: B. Phospholipase A2. Inhibited by steroids . Option: C. Superoxide dismutase. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Role of Arachidonic Acid Metabolites: Action Eicosanoid Vasodilation Prostaglandins PGI2 (prostacyclin), PGE, PGE2, PGD2 Vasoconstriction Thromboxane A2, leukotrienes C4, D4, E4 Increased vascular permeability Leukotrienes C4, D4, E4 Chemotaxis, leukocyte adhesion Leukotrienes B4, HETE HETE, Hydroxyeicosatetraenoic acid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 59-year-old man experiences acute chest pain and is rushed to the emergency room. Laboratory studies and ECG demonstrate an acute myocardial infarction; however, coronary artery angiography performed 2 hours later does not show evidence of thrombosis. Which of the following mediators of inflammation causes relaxation of vascular smooth muscle cells and vasodilation of arterioles at the site of myocardial infarction in this patient?", "options": [{"label": "A", "text": "Bradykinin", "correct": false}, {"label": "B", "text": "Histamine", "correct": false}, {"label": "C", "text": "Leukotrienes", "correct": false}, {"label": "D", "text": "Nitric oxide", "correct": true}], "correct_answer": "D. Nitric oxide", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nitric oxide Nitric oxide (NO) , previously known as an endothelium-derived relaxing factor , leads to the relaxation of vascular smooth muscle cells and vasodilation of arterioles . NO also inhibits platelet aggregation and mediates the killing of bacteria and tumor cells by macrophages. Histamine, leukotrienes and thromboxane A2 stimulate the contraction of smooth muscle cells. NO , a soluble gas produced from arginine by the action of nitric oxide synthase (NOS)</p>\n<p><strong>Highyeild:</strong></p><p>NO is synthesised from Arginine . Sites: Endothelium (eNO): Maintains vascular tone Nerves (nNO): Neurotransmitter Inducible (iNO): Inflammation Functions: Vasodilation Smooth muscle relaxation Reactive Oxygen Species table,tr,th,td {border:1px solid black;} Mediator Source Action Histamine Mast cells, basophils, platelets Vasodilation, increased vascular permeability, endothelial activation Prostaglandins Mast cells, leukocytes Vasodilation, pain, fever Leukotrienes Mast cells, leukocytes Increased vascular permeability, chemotaxis, leukocyte adhesion and activation Cytokines (TNF, IL-1, IL-6) Macrophages, endothelial cells, mast cells Local: endothelial activation (expression of adhesion molecules) Systemic: fever, metabolic abnormalities, hypotension (shock) Chemokines Leukocytes, activated macrophages Chemotaxis, leukocyte activation Platelet- activating factor Leukocytes, mast cells Vasodilation, increased vascular permeability, leukocyte adhesion, chemotaxis, degranulation, oxidative burst Complement Plasma (produced in liver) Leukocyte chemotaxis and activation, direct target killing (membrane attack complex), vasodilation (mast cell stimulation) Kinins Plasma (produced in liver Increased vascular permeability, smooth muscle contraction, vasodilation, pain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Bradykinin increases vascular permeability and causes the contraction of smooth muscle . Option: B. Histamine causes intense smooth muscle contraction, increases vascular permeability, and stimulates mucus secretion by nasal, bronchial, and gastric glands. Option: C. Leukotrienes. Cause bronchospasm and increases vascular permeability .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Rolling of leukocytes on endothelial cells is mediated by which of the following proteins?", "options": [{"label": "A", "text": "Selectins", "correct": true}, {"label": "B", "text": "Integrins", "correct": false}, {"label": "C", "text": "Transferrin", "correct": false}, {"label": "D", "text": "PECAM-1", "correct": false}], "correct_answer": "A. Selectins", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Selectins Rolling interactions of leukocytes are mediated by a family of proteins called selectins . 3 types of selectins: L - selectins (on leukocytes) E - selectin (on endothelium) P - selectin (on platelets, endothelium)</p>\n<p><strong>Highyeild:</strong></p><p>Cellular events of inflammation: Margination: WBC movement inside the lumen of a blood vessel. Occurs due to selectins . Rolling: WBC movement inside the lumen of a blood vessel. Occurs due to selectins (endothelium) and Sialyl Lewis X glycoprotein (WBC) . Adhesion: WBC movement inside the lumen of a blood vessel. Occurs due to ICAM and VCAM (endothelium) and β2 Integrins (WBC) . Diapedesis: WBC moves across the Occurs due to PECAM-1, aka CD31 . Chemotaxis: Movement of WBC along a chemical gradient.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Integrins: Firm adhesion of leukocytes to the endothelial cells is mediated by a family of leucocyte surface proteins called integrins. Option: C. Transferrin: Iron transporting protein . Option: D. PECAM-1: PECAM-1 (platelet endothelium cell adhesion molecule) is present in the intercellular junction between endothelial cells and helps in the migration of leucocytes .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "C3 complement is cleared by?", "options": [{"label": "A", "text": "CD 59", "correct": false}, {"label": "B", "text": "CD 55", "correct": true}, {"label": "C", "text": "Factor D", "correct": false}, {"label": "D", "text": "Factor E", "correct": false}], "correct_answer": "B. CD 55", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD 55 The complement system is a collection of plasma proteins that function mainly in host defence against microbes and in pathologic inflammatory reactions. It functions in both innate and adaptive immunity for defence against microbial pathogens.</p>\n<p><strong>Highyeild:</strong></p><p>The critical step in complement activation is the proteolysis of the third (and most abundant) component, C3 . Cleavage of C3 can occur by one of three pathways: Classical pathway Alternative pathway Lectin pathway The complement system has three main functions: Inflammation Opsonization and phagocytosis Cell lysis The activation of complement is tightly controlled by cell-associated and circulating regulatory proteins . Regulatory proteins can be overwhelmed when large amounts of complement are deposited on host cells and in tissues. The most important of these regulatory proteins are the following: C1 inhibitor: blocks the activation of C1, the first protein of the classical complement pathway. Inherited deficiency of this inhibitor is the cause of hereditary angioedema . Decay accelerating factor (DAF) ie CD55 and MIRL (Membrane Inhibitor of Reactive Lysis) ie CD59 . DAF prevents the formation of C3 convertases , and CD59 inhibits the formation of the membrane attack complex . Acquired deficiency can lead to paroxysmal nocturnal hemoglobinuria (PNH) . Complement Factor H inhibits the alternative pathway by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H cause an atypical form of Hemolytic Uremic Syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, C, D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true in respect of hereditary angioneurotic edema(HAE), except", "options": [{"label": "A", "text": "Deficiency of C1 inhibitor (C1INH)", "correct": false}, {"label": "B", "text": "Urticaria", "correct": false}, {"label": "C", "text": "Pruritus is usually absent", "correct": false}, {"label": "D", "text": "Autosomal recessive disorder", "correct": true}], "correct_answer": "D. Autosomal recessive disorder", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Autosomal recessive disorder Hereditary angioneurotic edema (HAE): It is caused by an inherited deficiency of C1 esterase inhibitor that results in excessive activation of the early components of the complement system and production of vasoactive mediators . It is an autosomal dominant Although the exact nature of the bioactive compound produced in hereditary angioedema is uncertain, these patients have episodes of edema affecting skin and mucosal surfaces such as the larynx and the gastrointestinal tract . This may result in life- threatening asphyxia or nausea, vomiting, and diarrhea after minor trauma or emotional stress . Acute attacks of hereditary angioedema can be treated with C1 inhibitor concentrates prepared from human plasma . Angioneurotic edema is classically non-pitting in nature . Urticaria(hives) may develop simultaneously, pruritus is not present .</p>\n<p><strong>Highyeild:</strong></p><p>The critical step in complement activation is the proteolysis of the third (and most abundant) component, C3 . Cleavage of C3 can occur by one of three pathways: Classical pathway Alternative pathway Lectin pathway The complement system has three main functions: Inflammation Opsonization and phagocytosis Cell lysis The activation of complement is tightly controlled by cell-associated and circulating regulatory proteins . Regulatory proteins can be overwhelmed when large amounts of complement are deposited on host cells and in tissues. The most important of these regulatory proteins are the following: C1 inhibitor: blocks the activation of C1, the first protein of the classical complement pathway. Inherited deficiency of this inhibitor is the cause of hereditary angioedema . Decay accelerating factor (DAF) ie CD55 and MIRL (Membrane Inhibitor of Reactive Lysis) ie CD59 . DAF prevents the formation of C3 convertases , and CD59 inhibits the formation of the membrane attack complex . Acquired deficiency can lead to paroxysmal nocturnal hemoglobinuria (PNH) . Complement Factor H inhibits the alternative pathway by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H cause an atypical form of Hemolytic Uremic Syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Deficiency of C1 inhibitor (C1INH). True . Option: B. Urticaria. True . Option: C. Pruritus is usually absent. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Deficiency of complement proteins C5to C8 leads to increased infection by which of the following?", "options": [{"label": "A", "text": "Streptococcus", "correct": false}, {"label": "B", "text": "Neisseria", "correct": true}, {"label": "C", "text": "Pseudomonas", "correct": false}, {"label": "D", "text": "Staphylococcus", "correct": false}], "correct_answer": "B. Neisseria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neisseria The terminal components of complement C5, 6, 7,8, and 9 are required to assemble the membrane attack complex (MAC) involved in the lysis of organisms . The deposition of the membrane attack complex on cells makes these cells permeable to water and ions and results in osmotic lysis of the cells . This role of complement is particularly important for killing microbes with thin cell walls , such as Neisseria , and deficiency of the terminal components of complement (except c9) predisposes Neisseria infections (gonococcal and meningococcal) .</p>\n<p><strong>Highyeild:</strong></p><p>The critical step in complement activation is the proteolysis of the third (and most abundant) component, C3 . Cleavage of C3 can occur by one of three pathways: Classical pathway Alternative pathway Lectin pathway The complement system has three main functions: Inflammation Opsonization and phagocytosis Cell lysis The activation of complement is tightly controlled by cell-associated and circulating regulatory proteins . Regulatory proteins can be overwhelmed when large amounts of complement are deposited on host cells and tissues. The most important of these regulatory proteins are the following: C1 inhibitor: blocks the activation of C1, the first protein of the classical complement pathway. Inherited deficiency of this inhibitor is the cause of hereditary angioedema . Decay accelerating factor (DAF) ie CD55 and MIRL (Membrane Inhibitor of Reactive Lysis) ie CD59 . DAF prevents the formation of C3 convertases , and CD59 inhibits the formation of the membrane attack complex . Acquired deficiency can lead to paroxysmal nocturnal hemoglobinuria (PNH) . Complement Factor H inhibits the alternative pathway by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H cause an atypical form of Hemolytic Uremic Syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, C, D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Endogenous chemoattractant is-", "options": [{"label": "A", "text": "C5a", "correct": true}, {"label": "B", "text": "Bacterial products", "correct": false}, {"label": "C", "text": "Lipopolysaccharide A", "correct": false}, {"label": "D", "text": "C8", "correct": false}], "correct_answer": "A. C5a", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C5a After exiting the circulation, leukocytes move in the tissues toward the site of injury by chemotaxis, defined as locomotion along a chemical gradient . Both exogenous and endogenous substances can act as chemoattractants . The most common exogenous agents are bacterial products , including peptides that possess an N-formyl methionine terminal amino acid and some lipids. Endogenous chemoattractants include several chemical mediators, including cytokines (e.g., IL-8 ), Components of the complement system (particularly C5a ) and arachidonic acid metabolites, mainly leukotriene B4 (LTB4) . This induces the polymerisation of actin at the leading edge of the cell, which allows the leading edge of the leukocyte to extend filopodia and results in Chemotaxis .</p>\n<p><strong>Highyeild:</strong></p><p>Cellular events of inflammation: Margination: WBC movement inside the lumen of a blood vessel. Occurs due to selectins . Rolling: WBC movement inside the lumen of a blood vessel. Occurs due to selectins (endothelium) and Sialyl Lewis X glycoprotein (WBC) . Adhesion: WBC movement inside the lumen of a blood vessel. Occurs due to ICAM and VCAM (endothelium) and β2 Integrins (WBC) . Diapedesis: WBC moves across the Occurs due to PECAM-1, aka CD31 . Chemotaxis: Movement of WBC along a chemical gradient.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options B, C, D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Complement responsible for activation of bacterial lysis is-", "options": [{"label": "A", "text": "C3a", "correct": false}, {"label": "B", "text": "C3b", "correct": false}, {"label": "C", "text": "C5-9", "correct": true}, {"label": "D", "text": "C5a", "correct": false}], "correct_answer": "C. C5-9", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C5-9 Membrane attack complex is responsible for cell lysis . It consists of C-5,6,7,8,9 complement proteins . Complement activation on cells also leads to the formation of the membrane attack complex, which disrupts membrane integrity by “ drilling holes ” through the lipid bilayer, thereby causing osmotic lysis of the cells . Deficiency of these late-acting components is associated with increased susceptibility to recurrent Neisseria (gonococcal and meningococcal) infections.</p>\n<p><strong>Highyeild:</strong></p><p>The critical step in complement activation is the proteolysis of the third (and most abundant) component, C3 . Cleavage of C3 can occur by one of three pathways: Classical pathway Alternative pathway Lectin pathway The complement system has three main functions: Inflammation Opsonization and phagocytosis Cell lysis The activation of complement is tightly controlled by cell-associated and circulating regulatory proteins . Regulatory proteins can be overwhelmed when large amounts of complement are deposited on host cells and tissues. The most important of these regulatory proteins are the following: C1 inhibitor: blocks the activation of C1, the first protein of the classical complement pathway. Inherited deficiency of this inhibitor is the cause of hereditary angioedema . Decay accelerating factor (DAF) ie CD55 and MIRL (Membrane Inhibitor of Reactive Lysis) ie CD59 . DAF prevents the formation of C3 convertases , and CD59 inhibits the formation of the membrane attack complex . Acquired deficiency can lead to paroxysmal nocturnal hemoglobinuria (PNH) . Complement Factor H inhibits the alternative pathway by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H cause an atypical form of Hemolytic Uremic Syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Options A, B, D are incorrect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are correct, except?", "options": [{"label": "A", "text": "Cause of aspirin-sensitive asthma is overproduction of leukotrienes due to COX inhibition", "correct": false}, {"label": "B", "text": "Complement C5a acts as a chemokine", "correct": false}, {"label": "C", "text": "Complement C3b acts as an opsonizer", "correct": false}, {"label": "D", "text": "Fibrinogen and C reactive proteins are negative acute phase reactants", "correct": true}], "correct_answer": "D. Fibrinogen and C reactive proteins are negative acute phase reactants", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fibrinogen and C reactive proteins are negative acute phase reactants Positive Acute Phase Reactants increase during inflammation. CRP and Fibrinogen are negative acute phase reactants. Elevated levels of acute-phase proteins (APR) , which are plasma proteins , mostly synthesized in the liver , whose plasma concentrations may increase several hundred–fold as part of the response to inflammatory stimuli.</p>\n<p><strong>Highyeild:</strong></p><p>Acute Phase Reactants: Positive Acute Phase Reactants Negative Acute Phase Reactants Fibrinogen Transferrin CRP Albumin Ferritin Transthyretin Haptoglobin Hepcidin Ceruloplasmin Serum amyloid (SAA)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Cause of aspirin-sensitive asthma is overproduction of leukotrienes as a result of COX inhibition. There will be a divergence of arachidonic acid metabolites towards LOX pathway as a result of COX inhibition, causing Aspirin-induced Asthma . Option: B. Complement C5a acts as a chemokine. True . Option: C. Complement C3b acts as an opsonizer. True .</p>\n<p><strong>Extraedge:</strong></p><p>Elevated serum levels of CRP have been proposed as a marker for increased risk of myocardial infarction in patients with coronary artery disease. It is postulated that inflammation involving atherosclerotic plaques in the coronary arteries may predispose to thrombosis and subsequent infarction. Hepcidin is a small protein that reduces the availability of iron to erythroid progenitors in the bone marrow; over time, this effect may lead to anemia or chronic inflammation . Thrombopoietin , the major growth factor for megakaryocytes (platelet precursors) in the bone marrow, is also upregulated and as a result systemic inflammation may be associated with an elevated platelet count ( thrombocytosis ). Acute-phase proteins have beneficial effects during acute inflammation, but prolonged production of these proteins (especially SAA ) in states of chronic inflammation causes secondary amyloidosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 72-year-old female reports that approximately 2 weeks ago, she noticed the onset of decreased vision in her left eye associated with a “black spot” close to the centre of her vision. The spot is present with both near and far vision and does not move away. The vision has been slightly blurred for a while. She denies any recent trauma, eye pain, redness or discharge. Peripheral vision is normal. The visual field she has is depicted below. This is correlated to which of the following?", "options": [{"label": "A", "text": "CD59 deficiency", "correct": false}, {"label": "B", "text": "Factor H polymorphism", "correct": true}, {"label": "C", "text": "C1 inhibitor deficiency", "correct": false}, {"label": "D", "text": "Decay accelerating factor deficiency", "correct": false}], "correct_answer": "B. Factor H polymorphism", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1686815879658-QTDP019046IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Factor H polymorphism Complement Factor H is a circulating glycoprotein that inhibits the alternative pathway of complement activation by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H and several other regulatory proteins that interact with Factor H cause an atypical form of the hemolytic uremic syndrome , in which complement deposits in glomerular vessels lead to endothelial damage and the formation of platelet-rich thrombi . Polymorphisms in the Factor H gene have also been linked to age-related macular degeneration , an important cause of vision loss in older adults.</p>\n<p><strong>Highyeild:</strong></p><p>The critical step in complement activation is the proteolysis of the third (and most abundant) component, C3 . Cleavage of C3 can occur by one of three pathways: Classical pathway Alternative pathway Lectin pathway The complement system has three main functions: Inflammation Opsonization and phagocytosis Cell lysis The activation of complement is tightly controlled by cell-associated and circulating regulatory proteins . Regulatory proteins can be overwhelmed when large amounts of complement are deposited on host cells and tissues. The most important of these regulatory proteins are the following: C1 inhibitor: blocks the activation of C1, the first protein of the classical complement pathway. Inherited deficiency of this inhibitor is the cause of hereditary angioedema . Decay accelerating factor (DAF) ie CD55 and MIRL (Membrane Inhibitor of Reactive Lysis) ie CD59 . DAF prevents the formation of C3 convertases , and CD59 inhibits the formation of the membrane attack complex . Acquired deficiency can lead to paroxysmal nocturnal hemoglobinuria (PNH) . Complement Factor H inhibits the alternative pathway by promoting the cleavage and destruction of C3b and the turnover of the C3 convertases . Inherited defects in Factor H cause an atypical form of Hemolytic Uremic Syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. CD59 deficiency. Deficiency leads to PNH . Option: C. C1 inhibitor deficiency. Deficiency leads to hereditary angioedema . Option: D. Decay accelerating factor deficiency. Deficiency leads to PNH .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 43 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 29-year-old woman at 7.5 weeks' gestation visits the physician for a routine prenatal examination. The patient says that her husband is affected by an inherited disease. Further evaluation reveals that the husband’s father is affected with the same disease, as is his paternal aunt and her son. There are many generations of affected individuals in the husband’s family. Which of the following is the most appropriate response by the physician?", "options": [{"label": "A", "text": "The child will be affected", "correct": false}, {"label": "B", "text": "The child will not be affected", "correct": false}, {"label": "C", "text": "The inheritance risk cannot be determined until the sex of the child is known", "correct": false}, {"label": "D", "text": "There is a 50% chance of the child having the disease", "correct": true}], "correct_answer": "D. There is a 50% chance of the child having the disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>There is a 50% chance of the child having the disease</p>\n<p><strong>Highyeild:</strong></p><p>EXAMPLES OF AUTOSOMAL DOMINANT System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some variants)a Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemiaª Acute intermittent porphyria The question points out the need to use an algorithm for determining the mode of inheritance in a pedigree. Since there is female-to-male transmission (paternal aunt and her son) , the disease gene could be either X-linked or Autosomal . Since there is male-to-male transmission (patient’s father to the patient) , the disease cannot be X-linked . Therefore, the disease gene must be autosomal . If multiple and successive generations are affected, the disease is most likely autosomal dominant and therefore has a 50% average recurrence risk for any progeny if one parent is affected . If multiple generations are unaffected, the disease would be more likely to be transmitted in an autosomal recessive manner, with a 25% recurrence risk if both parents are carriers.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. The child will be affected. It is not possible to say that the child absolutely will be affected. Option: B. The child will not be affected. It is impossible to say that the child will not be affected. Option: C. The inheritance risk cannot be determined until the sex of the child is known. It is not necessary to know the sex of the child since the pedigree shows that transmission of the disease is independent of the sex of the progeny .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 10-year-old boy comes to the physician for a physical examination. He is tall and has a bulging, “bird-like” chest. The boy’s joints are hypermobile with long and tapered fingers. His father suffered an aortic aneurysm at a young age. A mutation in which of the following genes is the most likely cause of the patient’s condition?", "options": [{"label": "A", "text": "ATP7A", "correct": false}, {"label": "B", "text": "COL1A1", "correct": false}, {"label": "C", "text": "FBN1", "correct": true}, {"label": "D", "text": "FMR1", "correct": false}], "correct_answer": "C. FBN1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FBN1 Marfan syndrome is an autosomal dominant connective tissue disorder with variable expression. This condition affects many organ systems, including the heart, skeleton, and eyes. Marfan syndrome is caused by a defective form of Fibrillin , a glycoprotein that forms a sheath around elastin fibres and that is encoded by the FBN1 gene (chromosome 15) . Clinical features: Tall with long extremities Hypermobile joints Arachnodactyly (tapering fingers and toes) Pectus carinatum (bulging, “bird-like” chest) or pectus excavatum (sunken, “caved-in” chest) Cardiovascular Cystic medial necrosis of the aorta Aortic dissection root or rupture of an aortic root aneurysm ( the most common cause of death in these patients ) Mitral valve prolapse Ocular Subluxation of lenses, generally temporally and upward</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. ATP7A. ATP7A encodes Menkes protein, a copper transporter implicated in Menkes disease , an X-linked recessive connective-tissue disease. Option: B . COL1A1. Osteogenesis imperfecta , a bone disorder most commonly caused by COL1A1 and COL1A2 gene defects , decreases normal type I collagen production. Option: D. FMR1. FMR1 is the affected gene in Fragile X syndrome , the most common inherited cause of intellectual disability . The X-linked dominant inheritance of a trinucleotide repeat in the FMR1 gene causes this syndrome</p>\n<p><strong>Extraedge:</strong></p><p>Marfan’s vs Homocystinuria Marfan syndrome Homocystinuria INHERITANCE Autosomal dominant Autosomal recessive INTELLECT Normal Decreased VASCULAR COMPLICATIONS Aortic root dilatation Thrombosis LENS DISLOCATION Upward/temporal (Marfan fans out) Downward/nasal</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 12-year-old boy with muscular dystrophy presented to the OPD. He has been a wheelchair user since the age of nine; initial symptoms started with progressive weakness in his lower limbs, and he has a family history that shows that the disease was transmitted in an X-linked recessive manner; he also had an uncle who died at the age of 19 years. Which of the following is most likely the diagnosis?", "options": [{"label": "A", "text": "Duchene muscular dystrophy", "correct": true}, {"label": "B", "text": "Becker muscular dystrophy", "correct": false}, {"label": "C", "text": "Lysosomal storage disorder", "correct": false}, {"label": "D", "text": "MELAS", "correct": false}], "correct_answer": "A. Duchene muscular dystrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Duchene muscular dystrophy</p>\n<p><strong>Highyeild:</strong></p><p>The symptoms described indicate that the patient suffers from Duchenne muscular dystrophy (DMD), caused by mutations in the DMD gene that encodes dystrophin, a cytoskeletal protein . Dystrophin: A protein with a flexible, rod-like structure having globular structures at either end. Part of the subsarcolemmal assembly anchors the contractile array to the sarcolemma and extracellular matrix. The absence of dystrophin (or dystrophin dysfunction) causes structural instability and promotes proteolytic degradation and muscle fibre degeneration . Duchen e Muscular Dystrophy and Becker Muscular Dystrophy are X-linked recessive .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Becker muscular dystrophy. BMD usually presents at an older age; the history of the child being a wheelchair user since 9 years goes more in favour of Duchene than Becker. Option: C. Lysosomal storage disorder. Lysosomal storage diseases such as Tay-Sachs and Niemann-Pick can present with progressive neurodegeneration, hypotonia, and failure to thrive within the first year of life . These conditions are autosomal recessive and are not associated with skeletal muscle defects . Option: D. MELAS. Mitochondrial myopathy, encephalopathy, lactic acidosis, and stroke, MELAS is a rare progressive neurodegenerative disorder that is either sporadic in origin or transmitted maternally via mitochondrial inheritance .</p>\n<p><strong>Extraedge:</strong></p><p>Features Duchene Muscular Dystrophy Becker Muscular Dystrophy Inheritance XR XR Gender mostly affected Males Males Dystrophin levels Decreased/ Abnormal Normal but defective Muscle involvement Proximal > Distal Proximal > Distal Grower’s sign Grower’s sign positive Grower’s sign positive Calf hypertrophy Calf hypertrophy seen Calf hypertrophy seen Presents in Child Adolescent/ Adult Presentation Unable to walk without support at < 12 years Able to walk without support beyond 15 years Serum Creatinine Kinase (CK) ● Increased. ● Peaks at 3-8 years and then decline, and can this be normal at presentation? ● Increased ● Peaks at 2nd and 3rd decade and then declines Cardiomyopathy May or may not be seen May or may not be seen Respiratory muscle involvement Seen Seen IQ Abnormal Rarely Abnormal</p>\n<p><strong>Table:</strong></p><p>Modes of inheritance: Autosomal Dominant: System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some variants)a Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemiaª Acute intermittent\n porphyria Autosomal Recessive: System Disorder Metabolic Cystic fibrosis Phenylketonuria Galactosemia Homocystinuria Lysosomal storage diseases α-Antitrypsin deficiency Wilson disease a Hemochromatosis Glycogen storage diseases a Hematopoietic Sickle cell anemia Thalassemias Endocrine Congenital adrenal hyperplasia Skeletal Ehlers-Danlos syndrome (some variants) a Alkaptonuria Nervous Neurogenic muscular atrophies Friedreich ataxia Spinal muscular atrophy X Linked Recessive: System Disease Musculoskeletal Duchenne muscular dystrophy Blood Hemophilia A and B Chronic granulomatous disease Glucose-6-phosphate dehydrogenase deficiency Immune Agammaglobulinemia Wiskott-Aldrich syndrome Metabolic Diabetes insipidus Lesch-Nyhan syndrome Nervous Fragile X syndrome 2</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Kinky hair disease is a disorder where an affected child has peculiar coarse kinky hair, fails to grow and thrive, and neurodegeneration is seen and usually dies by 2-3 years old. Mrs Seema is hesitant about having children because her two sisters had sons who had died from kinky hair disease. Also, her mother's brother died from the same condition. Which of the following is the possible mode of inheritance in her family and protein defect seen?", "options": [{"label": "A", "text": "X linked recessive, ATP7A", "correct": true}, {"label": "B", "text": "X linked recessive, ATP7B", "correct": false}, {"label": "C", "text": "Autosomal recessive, ATP7A", "correct": false}, {"label": "D", "text": "Autosomal recessive, ATP7B", "correct": false}], "correct_answer": "A. X linked recessive, ATP7A", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>X linked recessive, ATP7A The given disease manifests only in males ; therefore, it is sex-linked disease females are not affected , so they must be careers . This is a classical feature of X-linked recessive disorders. All sex-linked disorders are X-linked, and almost all are recessive. Several genes are located in the male-specific region of Y, all related to spermatogenesis. Males with mutations affecting the Y-linked genes are usually infertile; hence, there is no Y-linked inheritance. X-linked recessive inheritance accounts for a small number of well-defined clinical conditions. For the most part, the Y chromosome is not homologous to the X chromosome, so mutant genes on the X chromosome do not have corresponding alleles on the Y chromosome. Thus, males are said to be Hemizygous for X-linked mutant genes, so these disorders are expressed in males. Other features characterising these disorders are as follows: An affected male does not transmit the disorder to his sons, but all daughters are carriers. Of course, sons of heterozygous women have one chance in two of receiving the mutant gene. A heterozygous female usually does not express the complete phenotypic change because of the paired normal allele. Because of the random inactivation of one of the X chromosomes in the female, females have a variable proportion of cells in which the mutant X chromosome is active. Thus, the normal allele can be inactivated in most cells, permitting full expression of heterozygous X-linked conditions in females . X Linked Recessive: System Disease Musculoskeletal Duchenne muscular dystrophy Blood Hemophilia A and B Chronic granulomatous disease Glucose-6-phosphate dehydrogenase deficiency Immune Agammaglobulinemia Wiskott-Aldrich syndrome Metabolic Diabetes insipidus Lesch-Nyhan syndrome Nervous Fragile X syndrome 2</p>\n<p><strong>Highyeild:</strong></p><p>Menkes disease X-linked recessive connective tissue disease is caused by impaired copper absorption and transport due to defective Menkes protein ATP7A ( A bsent copper). This leads to decreased lysyl oxidase activity (copper is a necessary cofactor) and defective collagen cross-linking. Results in brittle, “kinky” hair, growth and developmental delay, hypotonia, and risk of cerebral aneurysms .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. X linked recessive, ATP7B. Incorrect Option: C. Autosomal recessive, ATP7A. Incorrect Option: D. Autosomal recessive, ATP7B. Seen in Wilson disease, aka Hepatolenticular degeneration , Presents before age 40 with liver disease and neurological disorders like dystopia, tremors, Kayser-Fleicher rings, hemolytic anaemia, and Fanconi syndrome.</p>\n<p><strong>Extraedge:</strong></p><p>Features Menke disease Wilson disease Serum Copper levels Low High Ceruloplasmin levels Low Low Defect ATP7A ( a bsence of copper) ATP7B ( b uildup of copper) Presents with Due to defective Lysol oxidase Decreased levels of methyl histidine in urine</p>\n<p><strong>Table:</strong></p><p>MENKE VS WILSON DISEASE Features Menke disease Wilson disease Serum Copper levels Low High Ceruloplasmin levels Low Low Defect ATP7A ( a bsence of\n copper) ATP7B ( b uildup of\n copper) Presents with Due to defective Lysol\n oxidase Decreased levels of methyl\n histidine in urine</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A couple, Mr and Mrs Sharma, presented to the OPD for suggestions for their conception. It was found that both husband and wife were suffering from achondroplasia. What is their chance of having a normal child?", "options": [{"label": "A", "text": "0 per cent", "correct": false}, {"label": "B", "text": "100 per cent", "correct": false}, {"label": "C", "text": "50 per cent", "correct": false}, {"label": "D", "text": "25 per cent", "correct": true}], "correct_answer": "D. 25 per cent", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>25 per cent Achondroplasia is autosomal dominant , so only one out of four children will be unaffected , which is 25% of the chances of having a normal child. Autosomal dominant disorders are manifested in the heterozygous state, so at least one parent of an index case is usually affected; both males and females are affected, and both can transmit the condition. When an affected person marries an unaffected one, every child has one chance in two of having the disease. In addition to these basic rules, autosomal dominant conditions are characterised by the following: With every autosomal dominant disorder, some patients do not have affected parents . Such patients owe their disorder to new mutations involving either the egg or the sperm they derived from . Their siblings are neither affected nor at increased risk for disease development . The proportion of patients who develop the disease due to a new mutation is related to the effect of the disease on reproductive capability. If a disease markedly reduces reproductive fitness, most cases would be expected to result from new mutations. Many new mutations occur in germ cells of relatively older fathers.</p>\n<p><strong>Highyeild:</strong></p><p>Achondroplasia is the most common skeletal dysplasia and a significant cause of dwarfism . It is an autosomal dominant disorder caused by gain-of-function mutations in the FGF receptor 3 (FGFR3) gene . The retarded cartilage growth results in shortened proximal extremities , an enlarged head with a bulging forehead , and depression of the root of the nose despite a trunk of relatively normal length . These skeletal abnormalities are not usually associated with longevity, intelligence, or reproductive status changes .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. 0 per cent. Incorrect . Option: B. 100 per cent. Incorrect . Option: C. 50 per cent. Incorrect .</p>\n<p><strong>Table:</strong></p><p>Modes of inheritance: Autosomal Dominant: System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some variants)a Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemiaª Acute intermittent\n porphyria</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following statements is correct regarding the condition shown in image?", "options": [{"label": "A", "text": "It occurs due to an excess of vitamin A", "correct": false}, {"label": "B", "text": "It involves reprogramming stem cells", "correct": true}, {"label": "C", "text": "It involves atrophy", "correct": false}, {"label": "D", "text": "It occurs due to over activation of the retinoic acid receptor", "correct": false}], "correct_answer": "B. It involves reprogramming stem cells", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811956725-QTDP004001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It involves reprogramming stem cells The condition shown in the image represents keratomalacia , which involves softening and destruction of the cornea . It occurs due to a deficiency of vitamin A . Vitamin A is needed for the differentiation of specialized epithelium such as conjunctiva. Hence, in deficiency of vitamin A , metaplasia of normal squamous lining of the conjunctiva to stratified keratinizing squamous epithelium And metaplasia involves the reprogramming of stem cells . Hence, the correct option is B.</p>\n<p><strong>Highyeild:</strong></p><p>Vitamin A is a fat-soluble vitamin. More than 90% of the body’s vitamin A reserves are stored in the liver, predominantly in the perisinusoidal stellate (Ito) cells Functions of Vitamin A: Maintenance of normal vision. Cell growth and differentiation. Metabolic effects of retinoids. Enhancing immunity to infections. Retinoids are used clinically in the treatment of skin disorders such as severe acne and certain forms of psoriasis , as well as in the treatment of acute promyelocytic leukaemia (all-trans-retinoic acid). Hypertrophy refers to an increase in cell size Hyperplasia refers to an increase in cell number Metaplasia refers to a change in the phenotype of a cell Atrophy refers to the reduction in the size of an organ or tissue Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It occurs due to excess vitamin A. Incorrect because keratomalacia occurs due to a deficiency of vitamin A . Option: C. It involves atrophy. Incorrect because keratomalacia is an example of metaplasia . Option: D. It occurs due to the over-activation of retinoic acid receptors. Incorrect because keratomalacia does not involve the upregulation of retinoic acid receptors .</p>\n<p><strong>Extraedge:</strong></p><p>Epidemiological markers for Vit A deficiency: Prevalence criteria for determining the xerophthalmia problem Criteria Prevalence in population at risk (6 months to 6 years) Nightblindness Bitot's spots Corneal xerosis/corneal ulceration/keratomalacia Corneal ulcer Serum retinol (less than 10 mcg/dl) more than 1 per cent more than 0.5 per cent more than 0.01 per cent more than 0.05 per cent more than 5 per cent RDA of Vitamin A is 600 micrograms for adults .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old woman has a 5-year history of heartburn with reflux esophagitis. She undergoes an endoscopic biopsy of the esophagus and the results are shown in the Image. What can be concluded about the patient’s condition from the given image?", "options": [{"label": "A", "text": "Intestinal metaplasia", "correct": true}, {"label": "B", "text": "Hypertrophy of epithelium", "correct": false}, {"label": "C", "text": "Hyperplasia of goblet cells", "correct": false}, {"label": "D", "text": "Malignant transformation", "correct": false}], "correct_answer": "A. Intestinal metaplasia", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1721215995463-photos-1686763515919-HYDP004002IMG2.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Intestinal metaplasia The given image represents Barrett’s esophagus , which is consistent with the columnar metaplasia of cells in the lower esophagus . It is an example of metaplasia in which squamous epithelium is replaced by columnar epithelium with goblet cells . This is also known as intestinal metaplasia . Hence, the correct answer is option A.</p>\n<p><strong>Highyeild:</strong></p><p>Barrett's esophagus can be recognized as tongues of red, velvety mucosa extending upward from the gastroesophageal junction. Histologic appearance of the gastroesophageal junction in Barrett's esophagus. Note the transition between esophageal squamous mucosa (left) and Barrett metaplasia, with abundant metaplastic goblet cells which are seen as mucin-filled glands (right). Goblet cells are diagnostic of Barrett’s.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Hypertrophy of epithelium. Incorrect because epithelium hypertrophy refers to an increase in the size of epithelial cells which is not seen in this case. Option: C. Hyperplasia of goblet cells. Incorrect because goblet cell hyperplasia is a feature of airway remodelling in asthma . Option: D. Malignant transformation. Incorrect because there is no malignant transformation yet . However, Barrett’s is a precancerous condition and increases the risk of carcinoma.</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis of Barrett’s requires endoscopy and biopsy showing evidence of metaplastic columnar mucosa above gastroesophageal junction and regular follow-up with endoscopy and biopsy to check for progression to Adenocarcinoma . Management of Barrett’s involves the use of Proton Pump Inhibitors . Goblet cells are the hallmark of the Intestinal type of metaplasia . These contain mucin and can be stained with Mucicarmine stain and Alicante blue (better) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 40-year-old male presents to the clinic with complaints of a cough for one month. He is a chronic smoker and has been smoking for 25 years. Which of the following changes are likely to be seen in the histopathological biopsy of this patient’s trachea?", "options": [{"label": "A", "text": "Squamous to columnar metaplasia", "correct": false}, {"label": "B", "text": "Columnar to squamous metaplasia", "correct": true}, {"label": "C", "text": "Connective tissue metaplasia", "correct": false}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "B. Columnar to squamous metaplasia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Columnar to squamous metaplasia A male who is a chronic smoker has an increased risk of developing columnar to squamous metaplasia of the trachea and bronchi . This occurs because squamous epithelium is able to survive under harsh circumstances . This is also the most common type of metaplasia Hence, the correct answer is B. Metaplasia of columnar to squamous epithelium. (A) Schematic diagram. (B) Metaplasia of columnar epithelium (left) to squamous epithelium (right) in a bronchus (as often occurs with smoking).</p>\n<p><strong>Highyeild:</strong></p><p>The following are seen in cancer cells : Anaplasia refers to a lack of differentiation . Pleomorphism refers to variations in the size and shape of the cell . Hyperchromasia coarsest clumped and darkly stained chromatin with irregular nuclei .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Squamous to columnar metaplasia. Incorrect because squamous to columnar metaplasia is seen in the case of Barrett's esophagus . Option: C. Connective tissue metaplasia. Incorrect because connective tissue metaplasia is seen in myositis ossificans .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 40-year-old woman has a history of heartburn and reflux esophagitis. Her biopsy findings indicate that she has Barrett’s esophagus. She is concerned about whether she is at an increased risk of esophageal cancer. Which type of cancer is this patient at the greatest risk for?", "options": [{"label": "A", "text": "Squamous cell carcinoma esophagus", "correct": false}, {"label": "B", "text": "Diffuse gastric carcinoma", "correct": false}, {"label": "C", "text": "Adenocarcinoma esophagus", "correct": true}, {"label": "D", "text": "Intestinal gastric carcinoma", "correct": false}], "correct_answer": "C. Adenocarcinoma esophagus", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adenocarcinoma esophagus This patient has Barrett esophagus which refers to the metaplasia of esophageal lining from squamous to columnar type in order to handle acid better. Thus, she is at an increased risk of developing adenocarcinoma of the lower esophagus . Hence, the correct option is C.</p>\n<p><strong>Highyeild:</strong></p><p>The greatest concern in Barrett's esophagus is that it confers an increased risk of esophageal adenocarcinoma, however, most individuals with Barrett’s esophagus do not develop esophageal tumours . NOTE: Barrett’s esophagus is not cancerous, it is precancerous . Barrett e'ssophagus can be recognized as tongues of red, velvety mucosa extending upward from the gastroesophageal junction. Histologic appearance of the gastroesophageal junction in Barrett's esophagus. Note the transition between esophageal squamous mucosa (left) and Barrett metaplasia, with abundant metaplastic goblet cells which are seen as mucin-filled glands (right). Goblet cells are diagnostic of Barrett’s.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Squamous cell carcinoma esophagus. Incorrect because squamous cell carcinoma of esophagus usually occurs due to risk factors such as cigarette smoke, hot foods, alcohol, smoky foods etc. Option: B. Diffuse gastric carcinoma. Incorrect because diffuse gastric carcinoma is usually seen due to nicotine use, a diet rich in nitrates etc. Option: D. Intestinal gastric carcinoma. Incorrect because intestinal gastric carcinoma is usually due to H. pylori infection, GERD etc.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 57-year-old male with a chronic cough, multiple respiratory infections and a 40-pack-year smoking history present with blood in his sputum. CXR reveals hyperinflated lungs without infiltrates or masses. Biopsy of bronchial mucosa reveals areas of stratified squamous epithelium. The pathogenesis of this patient’s microscopic findings is similar to which of the following conditions?", "options": [{"label": "A", "text": "Breast cancer", "correct": false}, {"label": "B", "text": "Myositis ossificans", "correct": true}, {"label": "C", "text": "Hypertrophic cardiomyopathy", "correct": false}, {"label": "D", "text": "Senile atrophy", "correct": false}], "correct_answer": "B. Myositis ossificans", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myositis ossificans The patient’s bronchial mucosa microscopic findings are suggestive of columnar to squamous metaplasia . This is because bronchial mucosa is normally lined by columnar epithelium but this patient has stratified squamous epithelium because of chronic smoking . This suggests that the patient’s bronchial mucosa has undergone metaplasia . Myositis ossificans is the only example of metaplasia from the above conditions . Hence, the correct answer is B.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results from the decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Breast cancer. Incorrect because breast cancer implies a neoplastic growth and it does not involve metaplasia Option: C. Hypertrophic cardiomyopathy. Incorrect because hypertrophic cardiomyopathy involves hypertrophy of cardiac smooth muscle fibres. Option: D. Senile atrophy. Incorrect because senile atrophy involves a decrease in the size and number of cells in the brain .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 40-year-old female has a history of heartburn and reflux esophagitis. A biopsy of the lower part of esophagus is taken and observed under a microscope. It shows columnar cells. Which of the following mechanism is responsible for this patient’s current condition?", "options": [{"label": "A", "text": "Increased multiplication of cells", "correct": false}, {"label": "B", "text": "Decreased protein synthesis", "correct": false}, {"label": "C", "text": "Reprogramming of stem cells", "correct": true}, {"label": "D", "text": "Increased protein synthesis", "correct": false}], "correct_answer": "C. Reprogramming of stem cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reprogramming of stem cells The given patient’s history of heartburn and biopsy findings reveal columnar cells are consistent with the diagnosis of Barrett’s esophagus. Now, Barrett’s esophagus is an example of metaplasia and metaplasia occurs due to the reprogramming of stem cells. Hence, the correct option is C.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. is incorrect because the increased multiplication of cells is seen in hyperplasia. Option: B. is incorrect because decreased protein synthesis is seen in atrophy. Option: D. is incorrect because increased protein synthesis is seen in hypertrophy.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 21-year-old male suffered a motor vehicle accident and in this accident, his elbow was injured. He underwent surgery in which a screw was used to fit his elbow. He returns after 17 days and now complains of restriction of movement as well as stiffness in the muscles of the affected part. An X-ray of the affected part is shown in the image. What is the likely diagnosis of the patient’s current condition?", "options": [{"label": "A", "text": "Hemorrhage", "correct": false}, {"label": "B", "text": "Fracture", "correct": false}, {"label": "C", "text": "Myositis ossificans", "correct": true}, {"label": "D", "text": "Elbow dislocation", "correct": false}], "correct_answer": "C. Myositis ossificans", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811965055-QTDP004007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myositis ossificans The patient’s history and X-ray findings are classic for myositis ossificans . Myositis ossificans is a metaplastic change that typically occurs after trauma , as evidenced by this patient’s accident. It involves metaplasia of muscular tissue into bony tissue which can be clearly seen on this X-ray as a hyperdense region around the elbow joint . Hence, the correct option is C. NOTE: Unlike epithelial metaplasia, this type of metaplasia is not associated with increased cancer risk.</p>\n<p><strong>Highyeild:</strong></p><p>Barrett's esophagus can be recognized as tongues of red, velvety mucosa extending upward from the gastroesophageal junction. Histologic appearance of the gastroesophageal junction in Barrett's esophagus. Note the transition between esophageal squamous mucosa (left) and Barrett metaplasia, with abundant metaplastic goblet cells which are seen as mucin-filled glands (right). Goblet cells are diagnostic of Barrett’s.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Incorrect because haemorrhage is usually an acute complication and on X-ray , they are seen as subperiosteal thickening . Option: B. Incorrect because the fracture presents with pain and a clear line of fracture can be seen on X-ray . Option: D. Elbow dislocation. Incorrect because elbow dislocation happened in this patient but it was corrected by surgery and hence, is not responsible for the patient's current findings .</p>\n<p><strong>Extraedge:</strong></p><p>Connective tissue metaplasia is the formation of cartilage, bone, or adipose cells (mesenchymal tissues) in tissues that normally do not contain these elements. For example, bone formation in muscle, designated myositis ossificans , occasionally occurs after intramuscular haemorrhage . It is more common in children because in them the periosteum is loosely attached to the bones, particularly common around the elbow joint. Massage following trauma is a factor known to aggravate myositis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following process is most similar to the process shown in the given image?", "options": [{"label": "A", "text": "Endometrial hyperplasia", "correct": false}, {"label": "B", "text": "Barrett’s esophagus", "correct": true}, {"label": "C", "text": "Osteoporosis of disuse", "correct": false}, {"label": "D", "text": "Enlarged heart due to hypertension", "correct": false}], "correct_answer": "B. Barrett’s esophagus", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/questionImage-1710502691411-WhatsAppImage2024-03-15at16.28.40_c66f5025.jpg"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Barrett’s esophagus The Image represents myositis ossificans which can be determined from the hyperdense region around the elbow joint. Moreover, the screw indicates that a recent surgery has been performed indicating a trauma. Myositis ossificans is an example of connective tissue metaplasia in which muscle changes to bone usually after trauma. Now, out of all the given options, only Barrett’s esophagus represents metaplasia. Hence, the correct option is B.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. is incorrect because endometrial hyperplasia is an example of hyperplasia. Option: C. is incorrect because osteoporosis of disuse is an example of atrophy. Option: D. is incorrect because an enlarged heart due to hypertension is an example of hypertrophy.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old male patient was diagnosed with colorectal cancer around 5 years ago. Currently, he is in an advanced stage of cancer. He looks emaciated and fatigued. He complained of weight loss and poor appetite. Which of the following enzymes plays a role in the patient’s current presentation?", "options": [{"label": "A", "text": "Ubiquitin ligase", "correct": true}, {"label": "B", "text": "Telomerase", "correct": false}, {"label": "C", "text": "Thymidylate synthase", "correct": false}, {"label": "D", "text": "TNF alpha", "correct": false}], "correct_answer": "A. Ubiquitin ligase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ubiquitin ligase The patient is in an advanced stage of colorectal cancer. The patient’s current condition is highly suggestive of cancer cachexia syndrome in which the patient experiences weight loss due to poor appetite and looks fatigued . Cachexia occurs due to atrophy and the enzyme that plays a role in atrophy is ubiquitin ligase which helps in attaching ubiquitin to proteins so that they are available to be degraded by proteasome . Hence, the correct option is A.</p>\n<p><strong>Highyeild:</strong></p><p>Decreased workload leads to Atrophy , which is a reduction in the size of tissue or organ which results a from decrease in cell number or size. It can be of two types: Physiological atrophy: During embryo development: During notochord formation. Loss of hormonal stimulation: Uterus after parturition , uterus, vagina and breast after menopause . Pathological atrophy: Disuse atrophy: due to decreased workload , seen in Atrophy of an immobilised limb after a fracture . Denervation atrophy: due to loss of nerve supply , seen in skeletal muscle atrophy following nerve injury , eg: Polio . Ischemic atrophy: due to atherosclerosis , seen in senile atrophy of the brain . Inadequate nutrition: Severe muscle wasting in Marasmus, Cancer cachexia . Pressure atrophy: Tumor compressing surrounding tissue .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Telomerase. Incorrect because increased telomerase expression is believed to result in cancer but this does not play a role in cachexia . Option: C. Thymidylate synthase. Incorrect because thymidylate synthase is an enzyme which plays a role in thymidine synthesis for DNA synthesis but it does not play any role in atrophy. Option: D. TNF alpha. Incorrect because though, TNF alpha plays a role in cachexia but TNF alpha is a cytokine and not an enzyme .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old man presented to the general physician with epigastric pain and heart-burn for 3 years. An upper GI endoscopy was done and the samples were taken. Histopathological examination revealed the following. Which of the following pathological findings suits the diagnosis?", "options": [{"label": "A", "text": "It is the result of stem cell reprogramming", "correct": true}, {"label": "B", "text": "It is the result of an increase in cell size", "correct": false}, {"label": "C", "text": "It is the result of the degradation of cellular proteinsthe by ubiquitin proteasome pathway", "correct": false}, {"label": "D", "text": "It is the result of columnar to squamous epithelial cell change", "correct": false}], "correct_answer": "A. It is the result of stem cell reprogramming", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811965242-QTDP004010IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is the result of stem cell reprogramming Barrett’s esophagus is the metaplasia from squamous to columnar cell type. Metaplasia occurs due to stem cell reprogramming.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Hypertrophy - increase in cell size. Option: C. Degradation of cellular proteins by ubiquitin-proteasome pathway occurs in Atrophy. Option: D. Columnar to squamous epithelial cell change – A type of metaplastic change occurring in the respiratory epithelium.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Find the false statement about metaplasia:", "options": [{"label": "A", "text": "Reversible", "correct": false}, {"label": "B", "text": "No loss of polarity", "correct": false}, {"label": "C", "text": "Reprogramming of stem cells", "correct": false}, {"label": "D", "text": "Pleomorphism present", "correct": true}], "correct_answer": "D. Pleomorphism present", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pleomorphism present Metaplasia is a reversible change in which one adult cell type (epithelial or mesenchymal) is replaced by another adult cell type . Metaplasia is thought to arise by reprogramming of stem cells to differentiate along a new pathway rather than a phenotypic change (trans-differentiation) of already differentiated cells. Loss of polarity and Pleomorphism are features of Anaplasia .</p>\n<p><strong>Highyeild:</strong></p><p>The following are seen in cancer cells : Anaplasia refers to a lack of differentiation . Pleomorphism refers to variations in the size and shape of the cell . Hyperchromasia coarsest clumped and darkly stained chromatin with irregular nuclei . Anaplastic tumor showing cellular and nuclear variation in size and shape. The prominent cell in the center field has an abnormal tripolar spindle.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 50-year-old man with chronic cystitis presents with complaints of urinary incontinence and pelvic discomfort. Biopsy of the bladder mucosa reveals foci of glandular epithelium and chronic inflammatory cells. No cytologic signs of atypia or malignancy are observed. Which of the following terms best describes the morphologic response to chronic injury in this patient?", "options": [{"label": "A", "text": "Metaplasia", "correct": true}, {"label": "B", "text": "Hyperplasia", "correct": false}, {"label": "C", "text": "Dysplasia", "correct": false}, {"label": "D", "text": "Neoplasia", "correct": false}], "correct_answer": "A. Metaplasia", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686811966501-QTDP004012IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Metaplasia Cystitis glandularis and cystitis cystica: These are common lesions of the urinary bladder in which nests of the urothelium (von Brunn nests) grow downward into the lamina propria . Here, epithelial cells in the centre of the nest undergo metaplasia and take on a cuboidal or columnar appearance ( cystitis glandularis ) or retract to produce cystic spaces lined by flattened urothelium ( cystitis cystica ). Because the two processes often coexist , the condition is typically referred to as cystitis cystica et glandularis . In a variant of cystitis, glandularis goblet cells are present, and the epithelium resembles intestinal mucosa (intestinal or colonic metaplasia). Both variants can arise in the setting of inflammation and metaplasia . Extensive and multifocal intestinal metaplasia is a precursor to adenocarcinoma .</p>\n<p><strong>Highyeild:</strong></p><p>Hypertrophy refers to an increase in cell size Hyperplasia refers to an increase in cell number Metaplasia refers to a Change in the phenotype of a cell Atrophy refers to a reduction in the size of an organ or tissue Anaplasia refers to a lack of differentiation Dysplasia is characterized by the loss in the uniformity of the individual cells and their architectural orientation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Hyperplasia does not involve stem cell reprogramming. It only increases the number of cells. Option: C. Dysplasia is a term that literally means “ disordered growth .” It is encountered principally in epithelial cells and is recognized on the basis of several morphologic changes. Dysplastic cells may exhibit considerable pleomorphism and often contain large hyperchromatic nuclei with a high nuclear-to-cytoplasmic ratio . Option: D. Neoplasia means new growth . The collection of cells and stroma composing new growths are referred to as neoplasms. The above clinical picture does not fit the characteristic of neoplasia as there is no cellular atypia/ malignancy .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 22 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "What is the etiology of \"bread and butter\" pericarditis, and in which clinical conditions is it typically observed?", "options": [{"label": "A", "text": "Serous inflammation, endocarditis", "correct": false}, {"label": "B", "text": "Purulent inflammation, pericardial effusion", "correct": false}, {"label": "C", "text": "Fibrinous inflammation, endocarditis", "correct": false}, {"label": "D", "text": "Fibrinous inflammation, rheumatic carditis", "correct": true}], "correct_answer": "D. Fibrinous inflammation, rheumatic carditis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686816003390-QTDP020002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fibrinous inflammation, rheumatic carditis A fibrinous exudate develops when the vascular leaks are large, or there is a local procoagulant stimulus . Histologically, fibrin appears as an eosinophilic meshwork of thread s or sometimes as an amorphous coagulum. Fibrinous exudates may be dissolved by fibrinolysis and cleared by macrophages. If the fibrin is not removed over time, it may stimulate the ingrowth of fibroblasts and blood vessels and thus lead to scarring . Conversion of the fibrinous exudate to scar tissue (organisation) within the pericardial sac leads to opaque, fibrous thickening of the pericardium and epicardium in the area of exudation and, if the fibrosis is extensive, obliteration of the pericardial space. Bread and butter pericarditis is seen in Rheumatic carditis .</p>\n<p><strong>Highyeild:</strong></p><p>The morphologic hallmarks of acute inflammatory reactions are the dilation of small blood vessels and the accumulation of leukocytes and fluid in the extravascular tissue . Catarrhal inflammation is the most common variant . It causes increased secretion of mucin . E.g., Sinusitis Serous inflammation is marked by exuding cell-poor fluid into spaces created by cell injury or body cavities lined by the peritoneum, pleura, or pericardium. It is the second most common type . E.g., Effusion, ascites, Bulla in burns . A fibrinous exudate develops when the vascular leaks are large, or there is a local procoagulant stimulus (e.g., caused by cancer cells). A fibrinous exudate is characteristic of inflammation in the lining of body cavities, such as the meninges, pericardium, and pleura. Eg: Bread and butter pericarditis (Rheumatic carditis) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Serous inflammation, endocarditis. Incorrect . Option: B. Purulent inflammation, pericardial effusion. Incorrect . Option: C. Fibrinous inflammation, endocarditis. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Purulent inflammation is characterised by the production of pus , an exudate of neutrophils , the liquefied debris of necrotic cells, and edema fluid. Eg: Acute appendicitis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is correct regarding serous inflammation?", "options": [{"label": "A", "text": "It is the most common type of acute inflammation", "correct": false}, {"label": "B", "text": "It can have bacterial growth", "correct": false}, {"label": "C", "text": "Causes an increase in mucin production", "correct": false}, {"label": "D", "text": "Collection of serous fluid in the cavities is called effusion", "correct": true}], "correct_answer": "D. Collection of serous fluid in the cavities is called effusion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Collection of serous fluid in the cavities is called effusion Serous inflammatio n is marked by exuding cell-poor fluid into spaces created by cell injury or body cavities lined by the peritoneum, pleura, or pericardium. In body cavities, the fluid may be derived from the plasma or the secretions of mesothelial cells. The accumulation of fluid in these cavities is called an effusion . Effusions also occur in noninflammatory conditions, such as reduced blood outflow in heart failure or reduced plasma protein levels in some kidney and liver diseases.</p>\n<p><strong>Highyeild:</strong></p><p>The morphologic hallmarks of acute inflammatory reactions are the dilation of small blood vessels and the accumulation of leukocytes and fluid in the extravascular tissue . Catarrhal inflammation is the most common variant . It causes increased secretion of mucin . E.g., Sinusitis Serous inflammation is marked by exuding cell-poor fluid into spaces created by cell injury or body cavities lined by the peritoneum, pleura, or pericardium. It is the second most common type . E.g., Effusion, ascites, Bulla in burns . A fibrinous exudate develops when the vascular leaks are large, or there is a local procoagulant stimulus (e.g., caused by cancer cells). A fibrinous exudate is characteristic of inflammation in the lining of body cavities, such as the meninges, pericardium, and pleura. Eg: Bread and butter pericarditis (Rheumatic carditis) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is the most common type of acute inflammation. It is the second most common type of inflammation. The most common type of inflammation is catarrhal inflammation. Option: B. It can have bacterial growth. Typically, the fluid in serous inflammation does not contain microbes or large numbers of leukocytes (which tend to produce purulent inflammation) Option: C. Causes an increase in mucin production. Mucin production is increased in catarrhal inflammation .</p>\n<p><strong>Extraedge:</strong></p><p>Purulent inflammation is characterised by the production of pus , an exudate of neutrophils , the liquefied debris of necrotic cells, and edema fluid. Eg: Acute appendicitis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding thrombi, except:", "options": [{"label": "A", "text": "Arterial/ cardiac thrombi form at the sight of turbulence or endothelial injury", "correct": false}, {"label": "B", "text": "Thrombi are focally attached to the point of initiation", "correct": false}, {"label": "C", "text": "Arterial Thrombi propagate away from the heart", "correct": true}, {"label": "D", "text": "Venous Thrombi are formed due to stasis and extend in the direction of blood flow", "correct": false}], "correct_answer": "C. Arterial Thrombi propagate away from the heart", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Arterial Thrombi propagate away from the heart. Arterial thrombi tend to grow retrograde, i.e. they propagate towards the heart.</p>\n<p><strong>Highyeild:</strong></p><p>Thrombosis and Virchow’s Triad: Thrombosis results due to: Endothelial injury Stasis or Turbulent blood flow Hypercoagulability of the blood. This is called Virchow's Triad . Arterial or cardiac thrombi usually begin at turbulence or endothelial injury sites , whereas venous thrombi characteristically occur at stasis sites . Thrombi are focally attached to the underlying vascular surface , particularly at the initiation . From here, arterial thrombi tend to grow retrograde , while venous thrombi extend in the direction of blood flow ; thus, BOTH propagate towards the heart .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Arterial/ cardiac thrombi form at the sight of turbulence or endothelial injury. Correct . Option: B. Thrombi are focally attached to the point of initiation. Correct . Option: D. Venous Thrombi are formed due to stasis and extend in the direction of blood flow. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False statement regarding lines of Zahn is-", "options": [{"label": "A", "text": "Lines of Zahn are seen grossly and microscopically", "correct": false}, {"label": "B", "text": "These signify antemortem clot", "correct": false}, {"label": "C", "text": "These have alternate deposits of pale platelet, fibrin and RBC deposition", "correct": false}, {"label": "D", "text": "Laminations signify that a thrombus is formed due to stasis", "correct": true}], "correct_answer": "D. Laminations signify that a thrombus is formed due to stasis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Laminations signify that a thrombus is formed due to stasis Thrombi often have grossly and microscopically apparent laminations called lines of Zahn , pale platelet and fibrin deposits alternating with darker red cell–rich layers . Such laminations signify that a thrombus has formed in flowing blood . Their presence can therefore distinguish antemortem clots from the bland non-laminated clots that occur post-mortem . Post-mortem clots have a Chicken fat appearance due to the settlement of RBcs under the fact layer.</p>\n<p><strong>Highyeild:</strong></p><p>Thrombosis and Virchow’s Triad: Thrombosis results due to: Endothelial injury Stasis or Turbulent blood flow Hypercoagulability of the blood. This is called Virchow's Triad . Arterial or cardiac thrombi usually begin at turbulence or endothelial injury sites , whereas venous thrombi characteristically occur at stasis sites . Thrombi are focally attached to the underlying vascular surface , particularly at the initiation . From here, arterial thrombi tend to grow retrograde , while venous thrombi extend in the direction of blood flow ; thus, BOTH propagate towards the heart .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Lines of Zahn are seen grossly and microscopically. Correct . Option: B. These signify antemortem clot. Correct . Option: C. These have alternate deposits of pale platelet, fibrin and RBC deposition. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All statements are true regarding arterial thrombi except:", "options": [{"label": "A", "text": "These are frequently occlusive", "correct": false}, {"label": "B", "text": "These consist of platelets, fibrin RBC and degenerated leukocytes", "correct": false}, {"label": "C", "text": "Cerebral artery is the most common to be involved", "correct": true}, {"label": "D", "text": "These are superimposed on the rupture of atherosclerotic plaques or vascular injury", "correct": false}], "correct_answer": "C. Cerebral artery is the most common to be involved", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cerebral artery is the most common to be involved Arterial thrombi are frequently occlusive . The most common sites in decreasing order of frequency are the coronary, cerebral, and femoral arteries . They typically consist of a friable meshwork of platelets, fibrin, red cells, and degenerating leukocytes . Although these are usually superimposed on a ruptured atherosclerotic plaque , other vascular injuries like vasculitis, and trauma may as well be the underlying cause .</p>\n<p><strong>Highyeild:</strong></p><p>Thrombosis and Virchow’s Triad: Thrombosis results due to: Endothelial injury Stasis or Turbulent blood flow Hypercoagulability of the blood This is called Virchow's Triad . Arterial or cardiac thrombi usually begin at turbulence or endothelial injury sites , whereas venous thrombi characteristically occur at stasis sites . Thrombi are focally attached to the underlying vascular surface , particularly at initiation . From here, arterial thrombi tend to grow retrograde , while venous thrombi extend in the direction of blood flow ; thus BOTH propagate towards the heart .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. These are frequently occlusive in nature. Correct . Option: B. These consist of platelets, fibrin RBC and degenerated leukocytes. Correct . Option: D. These are superimposed on rupture of atherosclerotic plaques or vascular injury. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding post-mortem clots except", "options": [{"label": "A", "text": "Gelatinous in nature", "correct": false}, {"label": "B", "text": "Attached to the underlying vessel", "correct": true}, {"label": "C", "text": "It can sometimes be confused with antemortem venous thrombi", "correct": false}, {"label": "D", "text": "Upper part is yellow, while the lower part is dark red", "correct": false}], "correct_answer": "B. Attached to the underlying vessel", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Attached to the underlying vessel Postmortem clots can sometimes be mistaken for Antemortem Venous Thrombi . However, clots that form after death are gelatinous and have a dark red dependent portion where red cells have settled by gravity and a yellow “chicken fat” upper portion and are usually NOT attached to the underlying vessel wall .</p>\n<p><strong>Highyeild:</strong></p><p>Thrombosis and Virchow’s Triad: Thrombosis results due to: Endothelial injury Stasis or Turbulent blood flow Hypercoagulability of the blood This is called Virchow's Triad . Arterial or cardiac thrombi usually begin at turbulence or endothelial injury sites , whereas venous thrombi characteristically occur at stasis sites . Thrombi are focally attached to the underlying vascular surface , particularly at initiation . From here, arterial thrombi tend to grow retrograde , while venous thrombi extend in the direction of blood flow ; thus BOTH propagate towards the heart .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Gelatinous in nature. Correct . Option: C. Can sometimes be confused with antemortem venous thrombi. Correct . Option: D. Upper part is yellow while the lower part is dark red. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding DVT, except:", "options": [{"label": "A", "text": "DVT can embolise the lungs", "correct": false}, {"label": "B", "text": "50% of the cases are usually asymptomatic", "correct": false}, {"label": "C", "text": "It usually involves a large leg vein at or above the knee", "correct": false}, {"label": "D", "text": "Bed rest helps in the prevention of DVT", "correct": true}], "correct_answer": "D. Bed rest helps in the prevention of DVT", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bed rest helps in the prevention of DVT Prolonged Bed rest predisposes to Deep Vein Thrombosis.</p>\n<p><strong>Highyeild:</strong></p><p>Venous Thrombosis: Most venous thrombi occur in the superficial or deep veins of the leg . Superficial venous thrombi typically occur in the saphenous veins in the setting of varicosities . Such thrombi can cause local congestion, swelling, pain, and tenderness, but rarely embolize, but predispose the overlying skin to develop infection and ulcers (varicose ulcers) . Deep venous thrombosis (DVT) involving one of the large leg veins— at or above the knee (e.g., the popliteal, femoral, and iliac veins) —is more serious because such thrombi more often embolise to the lungs and give rise to pulmonary infarction . DVTs are asymptomatic in approximately 50% of affected individuals and are recognised only in retrospect after embolisation . Common predisposing factors include: Bed rest and immobilisation Trauma Recent surgery (joint replacement especially) Trauma Obesity Malignancy Smoking OCP use Pregnancy and postpartum</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. DVT can embolise the lungs. Correct . Option: B. 50% of the cases are usually asymptomatic. Correct . Option: C. usually involves a large leg vein at or above the knee. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Well’s criteria for Pulmonary Embolism: Criteria Score Signs & Symptoms of DVT 3 Alternative diagnosis less likely 3 HR > 100/min 1.5 Immobilisation > 3 days or Surgery within 4 weeks 1.5 Prior H/o of DVT or PE 1.5 Cancer 1 Hemoptysis 1</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following mentioned antibody was seen in dermatomyositis except:", "options": [{"label": "A", "text": "Anti Mi2", "correct": false}, {"label": "B", "text": "Anti Jo1", "correct": false}, {"label": "C", "text": "Anti 155/P140", "correct": false}, {"label": "D", "text": "Anti CV2", "correct": true}], "correct_answer": "D. Anti CV2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anti CV2 Anti-CV2 antibodies are not commonly found in dermatomyositis. Instead, they are more commonly associated with a paraneoplastic syndrome known as encephalomyelitis with rigidity and myoclonus (PERM), which is a rare neurological disorder characterized by stiffness, rigidity, and involuntary muscle movements.</p>\n<p><strong>Highyeild:</strong></p><p>Dermatomyositis (DM) is an idiopathic inflammatory myopathy characterized by skeletal muscle weakness and skin changes. Genetic predisposition: PTPN22 gene and HLA associations Cutaneous Features: Heliotrope rash: Bilateral discoloration of the eyelids with swelling of eyelids and skin around the eyes. Shawl sign: Fixed redness affecting the back, shoulder, and chest Photosensitivity: Sunreaction over the ‘V area’ Gottron Papules: Violaceous papules over the joints of hands Gottron sign: Redness over knees, elbows, knees Nailfold changes: Loss of cuticles/ragged cuticles with nail fold redness Nail fold dermoscopy: Shows dilated capillaries Calcinosis cutis Raynaud phenomenon Flagellate erythema : characterized by multiple, red, macular streaks occurring on the trunk and proximal limbs. The stripes are aligned diagonally giving the appearance of whipping. Myositis of dermatomyositis Muscle weakness appears at the same time as the skin rash It usually affects proximal muscles Muscle pain and tenderness may be present</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Anti-Mi2: These antibodies (directed against a helicase implicated in nucleosome remodeling) show a strong association with prominent Gottron papules and heliotrope rash. Option: B. Anti-Jo1: These antibodies (directed against the enzyme histidyl t-RNA synthetase) are associated with interstitial lung disease, non-erosive arthritis, and a skin rash described as “mechanic’s hands.” Option: C. Anti-P155/P140: These antibodies (directed against several transcriptional regulators) are associated with paraneoplastic and juvenile cases of dermatomyositis.</p>\n<p><strong>Table:</strong></p><p>Inflammatory myopathy Dermatomyositis Inclusion body myositis Polymyositis Onset -Juvenile dermatomyositis - around 7 years of age ( Most common inflammatory\n myopathy in children) -Adult dermatomyositis - 4th to 6th-decade Elderly, > 50 years (Most common inflammatory\n myopathy in adults) >18 years Cutaneous involvement Present Absent Absent Myositis Symmetric Asymmetric Symmetric Histopathological findings -Perimysial CD4+ T cellular infiltrate -Perivascular infiltrates and perifascicular\n atrophy - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates Association Ovarian and other internal\n malignancy Infrequent Other autoimmune diseases and\n sometimes internal malignancy Steroid/ Immunotherapy Responsive Resistant Responsive</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a typical histological finding in dermatomyositis?", "options": [{"label": "A", "text": "Epidermal hyperplasia", "correct": false}, {"label": "B", "text": "Increased melanin pigmentation", "correct": false}, {"label": "C", "text": "Lichenoid inflammation", "correct": false}, {"label": "D", "text": "Perivascular inflammation with muscle fiber necrosis", "correct": true}], "correct_answer": "D. Perivascular inflammation with muscle fiber necrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Perivascular inflammation with muscle fiber necrosis Perivascular inflammation with muscle fiber necrosis is a typical feature of dermatomyositis. There is inflammation around small blood vessels (perivascular inflammation) in the muscle tissue, leading to damage and necrosis of the muscle fibers. This can result in weakness and wasting of the affected muscles.</p>\n<p><strong>Highyeild:</strong></p><p>Dermatomyositis (DM) is an idiopathic inflammatory myopathy characterized by skeletal muscle weakness and skin changes. Genetic predisposition: PTPN22 gene and HLA associations Cutaneous Features: Heliotrope rash: Bilateral discoloration of the eyelids with swelling of eyelids and skin around the eyes. Shawl sign: Fixed redness affecting the back, shoulder, and chest Photosensitivity: Sunreaction over the ‘V area’ Gottron Papules: Violaceous papules over the joints of hands Gottron sign: Redness over knees, elbows, knees Nailfold changes: Loss of cuticles/ragged cuticles with nail fold redness Nail fold dermoscopy: Shows dilated capillaries Calcinosis cutis Raynaud phenomenon Flagellate erythema : characterized by multiple, red, macular streaks occurring on the trunk and proximal limbs. The stripes are aligned diagonally giving the appearance of whipping. Myositis of dermatomyositis Muscle weakness appears at the same time as the skin rash It usually affects proximal muscles Muscle pain and tenderness may be present</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Epidermal hyperplasia: This finding is not specific to dermatomyositis and can be seen in a variety of skin conditions, such as psoriasis, lichen planus, and eczema. Option: B. Increased melanin pigmentation: This finding is also not specific to dermatomyositis and can be seen in conditions such as melasma, post-inflammatory hyperpigmentation, and drug-induced pigmentation. Option: C. Lichenoid inflammation: This finding is more commonly seen in lichen planus, a different skin condition characterized by itchy, purple, polygonal papules and plaques.</p>\n<p><strong>Table:</strong></p><p>Inflammatory myopathy Dermatomyositis Inclusion body myositis Polymyositis Onset -Juvenile dermatomyositis - around 7 years of age ( Most common inflammatory myopathy in children) -Adult dermatomyositis - 4th to 6th-decade Elderly, > 50 years (Most common inflammatory myopathy in adults) >18 years Cutaneous involvement Present Absent Absent Myositis Symmetric Asymmetric Symmetric Histopathological findings -Perimysial CD4+ T cellular infiltrate -Perivascular infiltrates and perifascicular atrophy - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates Association Ovarian and other internal malignancy Infrequent Other autoimmune diseases and sometimes internal malignancy Steroid/ Immunotherapy Responsive Resistant Responsive</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Gottron patch and heliotrope rash are seen in:", "options": [{"label": "A", "text": "Dermatomyositis", "correct": true}, {"label": "B", "text": "Polymyositis", "correct": false}, {"label": "C", "text": "Inclusion body myosotis", "correct": false}, {"label": "D", "text": "Toxic myopathies", "correct": false}], "correct_answer": "A. Dermatomyositis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dermatomyositis Gottron's patches and heliotrope rash are classic cutaneous features seen in dermatomyositis .</p>\n<p><strong>Highyeild:</strong></p><p>Dermatomyositis (DM) is an idiopathic inflammatory myopathy characterized by skeletal muscle weakness and skin changes. Genetic predisposition: PTPN22 gene and HLA associations Cutaneous Features: Heliotrope rash: Bilateral discoloration of the eyelids with swelling of eyelids and skin around the eyes. Shawl sign: Fixed redness affecting the back, shoulder, and chest Photosensitivity: Sunreaction over the ‘V area’ Gottron Papules: Violaceous papules over the joints of hands Gottron sign: Redness over knees, elbows, knees Nailfold changes: Loss of cuticles/ragged cuticles with nail fold redness Nail fold dermoscopy: Shows dilated capillaries Calcinosis cutis Raynaud phenomenon Flagellate erythema : characterized by multiple, red, macular streaks occurring on the trunk and proximal limbs. The stripes are aligned diagonally giving the appearance of whipping. Myositis of dermatomyositis Muscle weakness appears at the same time as the skin rash It usually affects proximal muscles Muscle pain and tenderness may be present</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Polymyositis: It typically presents with symmetrical proximal muscle weakness without skin involvement. Option: C. Inclusion body myositis: It is a chronic, slowly progressive inflammatory myopathy that primarily affects older adults and is characterized by muscle weakness, particularly in the hands, wrists, and fingers. Option: D. Toxic myopathies: These are caused by exposure to drugs or toxins and do not typically present with skin involvement.</p>\n<p><strong>Table:</strong></p><p>Inflammatory myopathy Dermatomyositis Inclusion body myositis Polymyositis Onset -Juvenile dermatomyositis - around 7 years of age ( Most common inflammatory myopathy in children) -Adult dermatomyositis - 4th to 6th-decade Elderly, > 50 years (Most common inflammatory myopathy in adults) >18 years Cutaneous involvement Present Absent Absent Myositis Symmetric Asymmetric Symmetric Histopathological findings -Perimysial CD4+ T cellular infiltrate -Perivascular infiltrates and perifascicular atrophy - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates Association Ovarian and other internal malignancy Infrequent Other autoimmune diseases and sometimes internal malignancy Steroid/ Immunotherapy Responsive Resistant Responsive</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of polymyositis except:", "options": [{"label": "A", "text": "Inflammatory infiltrate was seen in the endomysial region", "correct": false}, {"label": "B", "text": "Perifascicular atrophy", "correct": true}, {"label": "C", "text": "Degenerating necrosis of myofiber", "correct": false}, {"label": "D", "text": "Regenerating myofibre", "correct": false}], "correct_answer": "B. Perifascicular atrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Perifascicular atrophy Perifascicular atrophy is a histological feature typically seen in dermatomyositis, not polymyositis. Polymyositis is a type of inflammatory myopathy characterized by inflammatory infiltrates in the endomysial region of skeletal muscle fibers, leading to degenerating necrosis of myofibers and subsequent regeneration.</p>\n<p><strong>Highyeild:</strong></p><p>Polymyositis Inflammatory myopathy with progressive symmetric proximal muscle weakness Age of onset: >18 years Most common myositis associated with autoimmune conditions Most often involves shoulders Histology: Endomysial CD8+ cellular infiltrate and Perivascular infiltrates</p>\n<p><strong>Table:</strong></p><p>Inflammatory myopathy Dermatomyositis Inclusion body myositis Polymyositis Onset -Juvenile dermatomyositis - around 7 years of age ( Most common inflammatory myopathy in children) -Adult dermatomyositis - 4th to 6th-decade Elderly, > 50 years (Most common inflammatory myopathy in adults) >18 years Cutaneous involvement Present Absent Absent Myositis Symmetric Asymmetric Symmetric Histopathological findings -Perimysial CD4+ T cellular infiltrate -Perivascular infiltrates and perifascicular atrophy - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates Association Ovarian and other internal malignancy Infrequent Other autoimmune diseases and sometimes internal malignancy Steroid/ Immunotherapy Responsive Resistant Responsive</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are features of inclusion body myositis except:", "options": [{"label": "A", "text": "Endomysial inflammatory infiltrate composed of polymorphs", "correct": true}, {"label": "B", "text": "Rimmed vacuole", "correct": false}, {"label": "C", "text": "Admixture of degenerative and regenerative myofiber", "correct": false}, {"label": "D", "text": "cN1A antibody can be seen", "correct": false}], "correct_answer": "A. Endomysial inflammatory infiltrate composed of polymorphs", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Endomysial inflammatory infiltrate composed of polymorphs Inclusion body myositis (IBM) is characterized by the presence of endomysial inflammatory infiltrates primarily composed of CD8+ T cells, not polymorphs.</p>\n<p><strong>Highyeild:</strong></p><p>Inclusion body myositis Most common inflammatory myopathy in elderly Asymmetric muscle weakness Antibodies to cN1A present Histology: Endomysial CD8+ cellular infiltrate and Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles Laboratory findings: Modestly elevated creatine kinase levels</p>\n<p><strong>Table:</strong></p><p>Inflammatory myopathy Dermatomyositis Inclusion body myositis Polymyositis Onset -Juvenile dermatomyositis - around 7 years of age ( Most common inflammatory myopathy in children) -Adult dermatomyositis - 4th to 6th-decade Elderly, > 50 years (Most common inflammatory myopathy in adults) >18 years Cutaneous involvement Present Absent Absent Myositis Symmetric Asymmetric Symmetric Histopathological findings -Perimysial CD4+ T cellular infiltrate -Perivascular infiltrates and perifascicular atrophy - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates with amyloid inclusion bodies and rimmed vacuoles - Endomysial CD8+ cellular infiltrate -Perivascular infiltrates Association Ovarian and other internal malignancy Infrequent Other autoimmune diseases and sometimes internal malignancy Steroid/ Immunotherapy Responsive Resistant Responsive</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the inheritance pattern of Duchenne muscular dystrophy?", "options": [{"label": "A", "text": "Autosomal dominant", "correct": false}, {"label": "B", "text": "Autosomal recessive", "correct": false}, {"label": "C", "text": "X-linked recessive", "correct": true}, {"label": "D", "text": "Mitochondrial transmission", "correct": false}], "correct_answer": "C. X-linked recessive", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>X-linked recessive Duchenne muscular dystrophy (DMD) is inherited in an X-linked recessive pattern.</p>\n<p><strong>Highyeild:</strong></p><p>Duchenne muscular dystrophy (DMD) It is an X-linked recessive disorder that primarily affects males. Cause: Mutation in the DMD gene, which codes for the protein dystrophin. Pathophysiology: Dystrophin is an important protein that helps maintain the structure and stability of muscle fibers. In DMD, the absence of dystrophin leads to progressive muscle weakness and wasting. Features: Symptoms appear in early childhood Difficulty walking, frequent falls, and muscle weakness in the hips, thighs, and shoulders. As the disease progresses, it can affect the heart and respiratory muscles, leading to life-threatening complications. Most boys with DMD lose the ability to walk by their teenage years and typically die in their 20s or 30s. Gower sign: Patient uses upper extremity to stand up Diagnosis : Increased CK and aldolase, genetic testing</p>\n<p><strong>Extraedge:</strong></p><p>Clinical features of Duchenne Muscular Dystrophy</p>\n<p><strong>Table:</strong></p><p>Muscular\n dystrophies Type of Muscular Dystrophy Inheritance Defective gene Onset age Clinical features Duchenne’s XR Dystrophin Before 5 years Progressive weakness of girdle muscles Unable to walk after age 12 Progressive kyphoscoliosis Respiratory failure in 2nd or 3rd decade Becker's XR Dystrophin Early childhood to adult Progressive weakness of girdle muscles Able to walk after age 15 Respiratory failure may develop by 4th decade Limb-girdle AD/AR Several Early childhood to early adult Slow progressive weakness of shoulder and hip girdle muscles Emery-Dreifuss XR/AD Emerin/Lamins A/C Nesprin-1, Nesprin 2, TMEM43 Childhood to adult Elbow contractures, humeral and peroneal weakness Congenital AR Several At birth or within the first few months Hypotonia, contractures delayed milestones Progression to respiratory failure in some; static course in\n others Facioscapulo-humoral AD DUX4 4q Childhood to adult Slowly progressive weakness of the face, shoulder girdle, and\n foot dorsiflexion Myotonic AD Expansion of CTG repeat Childhood to adult Slowly progressive weakness of the face, shoulder girdle, and foot dorsiflexion Oculopharyngeal AD Expansion, poly-A RNA binding protein 5th to 6th decade Slowly progressive weakness of extraocular, pha- ryngeal, and\n limb muscles</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Duchenne and Becker's muscular dystrophy is caused by loss of function mutation of-", "options": [{"label": "A", "text": "Dystrophin", "correct": true}, {"label": "B", "text": "Dystrobrevin", "correct": false}, {"label": "C", "text": "Caveoline", "correct": false}, {"label": "D", "text": "Syntrophins", "correct": false}], "correct_answer": "A. Dystrophin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dystrophin Duchenne and Becker muscular dystrophy is caused by a loss of function mutation of the dystrophin gene, which is located on the X chromosome. Dystrophin is a structural protein that helps anchor muscle fibers to the extracellular matrix, and its absence or dysfunction leads to muscle degeneration and weakness, which are the hallmarks of DMD and BMD.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Dystrobrevin: It is a component of the dystrophin-associated protein complex (DAPC) and plays a role in linking dystrophin to the transmembrane proteins that interact with the extracellular matrix. However, mutations in dystrobrevin are not associated with DMD or BMD. Option: C. Caveoline: It is a structural protein found in caveolae, which are small invaginations in the plasma membrane. Caveolinopathies are a group of muscular dystrophies caused by mutations in the caveolin-3 gene, but they are distinct from DMD and BMD. Option: D. Syntrophins: These are also components of the DAPC, and they are thought to regulate the function of the complex by binding to and recruiting signaling molecules. However, mutations in syntrophins are not associated with DMD or BMD.</p>\n<p><strong>Table:</strong></p><p>Muscular dystrophies Type of Muscular Dystrophy Inheritance Defective gene Onset age Clinical features Duchenne’s XR Dystrophin Before 5 years Progressive weakness of girdle muscles Unable to walk after age 12 Progressive kyphoscoliosis Respiratory failure in 2nd or 3rd decade Becker's XR Dystrophin Early childhood to adult Progressive weakness of girdle muscles Able to walk after age 15 Respiratory failure may develop by 4th\n decade Limb-girdle AD/AR Several Early childhoods to early adult Slow progressive weakness of shoulder and\n hip girdle muscles Emery-Dreifuss XR/AD Emerin/Lamins A/C Nesprin-1, Nesprin 2, TMEM43 Childhood to adult Elbow contractures, humeral and peroneal\n weakness Congenital AR Several At birth or within the first few months Hypotonia, contractures delayed milestones Progression to respiratory failure in some;\n static course in others Facioscapulo-humoral AD DUX4 4q Childhood to adult Slowly progressive weakness of the face,\n shoulder girdle, and foot dorsiflexion Myotonic AD Expansion of CTG repeat Childhood to adult Slowly progressive weakness of the face,\n shoulder girdle, and foot dorsiflexion Oculopharyngeal AD Expansion, poly-A RNA binding protein 5th to 6th decade Slowly progressive weakness of extraocular,\n pha- ryngeal, and limb muscles</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of Becker muscular dystrophy except:", "options": [{"label": "A", "text": "There is segmental degeneration and regeneration of myofibre", "correct": false}, {"label": "B", "text": "Atrophic myofibre is seen", "correct": false}, {"label": "C", "text": "Dense inflammatory infiltrate in endomysial", "correct": true}, {"label": "D", "text": "Muscle tissue is replaced by fat and collagen", "correct": false}], "correct_answer": "C. Dense inflammatory infiltrate in endomysial", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dense inflammatory infiltrate in endomysial The dense inflammatory infiltrate in the endomysial is not a typical finding in BMD. Inflammatory infiltrates are more commonly seen in autoimmune myopathies or infectious myositis.</p>\n<p><strong>Highyeild:</strong></p><p>Becker muscular dystrophy (BMD) It is an X-linked recessive disorder caused by a mutation in the dystrophin gene. It is characterized by progressive muscle weakness and wasting, but the symptoms are usually milder than those seen in Duchenne muscular dystrophy (DMD). Histological findings of BMD Segmental necrosis and regeneration of muscle fibers Infiltration of muscle fibers by macrophages and lymphocytes Muscle fiber hypertrophy and hyperplasia Presence of fibrosis and fatty infiltration in muscle tissue Presence of dystrophin protein on muscle biopsy, but the amount may be reduced or abnormal</p>\n<p><strong>Table:</strong></p><p>Muscular\n dystrophies Type of Muscular Dystrophy Inheritance Defective gene Onset age Clinical features Duchenne’s XR Dystrophin Before 5 years Progressive weakness of girdle muscles Unable to walk after age 12 Progressive kyphoscoliosis Respiratory failure in 2nd or 3rd decade Becker's XR Dystrophin Early childhood to adult Progressive weakness of girdle muscles Able to walk after age 15 Respiratory failure may develop by 4th decade Limb-girdle AD/AR Several Early childhood to early adult Slow progressive weak- ness of shoulder and hip girdle muscles Emery-Dreifuss XR/AD Emerin/Lamins A/C Nesprin-1, Nesprin 2, TMEM43 Childhood to adult Elbow contractures, humeral and peroneal weakness Congenital AR Several At birth or within first few months Hypotonia, contractures delayed milestones Progression to respiratory failure in some; static course in\n others Facioscapulo-humoral AD DUX4 4q Childhood to adult Slowly progressive weak- ness of face, shoulder girdle, and foot\n dorsiflexion Myotonic AD Expansion of CTG repeat Childhood to adult Slowly progressive weak- ness of face, shoulder girdle, and foot\n dorsiflexion Oculopharyngeal AD Expansion, poly-A RNA binding protein 5th to 6th decade Slowly progressive weak- ness of extraocular, pha- ryngeal, and\n limb muscles</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the mentioned disease is caused by expansion of CTG triplets repeat?", "options": [{"label": "A", "text": "Duchenne muscular dystrophy", "correct": false}, {"label": "B", "text": "Myotonic dystrophy", "correct": true}, {"label": "C", "text": "Emery- Dreifuss muscular dystrophy", "correct": false}, {"label": "D", "text": "Limb-girdle muscular dystrophy", "correct": false}], "correct_answer": "B. Myotonic dystrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myotonic dystrophy Myotonic dystrophy is a type of muscular dystrophy caused by an abnormal expansion of a CTG triplet repeat in the DMPK gene on chromosome 19.</p>\n<p><strong>Highyeild:</strong></p><p>Myotonic Dystrophy Autosomal dominant disorder Age of onset: 20 to 30 years Cause: CTG trinucleotide repeat expansion in the DMPK gene leading to abnormal expression of myotonin protein kinase Features: Myotonia : Difficulty releasing hand from handshake Muscle wasting Cataracts : Fir tree appearance Testicular atrophy Frontal balding Conduction abnormality: arrhythmias Treatment: Mexiletene</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Duchenne muscular dystrophy: It (DMD) is caused by a mutation in the DMD gene on the X chromosome, leading to the absence or decreased production of the dystrophin protein. It is inherited in an X-linked recessive pattern. Option: C. Emery-Dreifuss muscular dystrophy: It (EDMD) is caused by mutations in several genes, including EMD and LMNA, and is inherited in an X-linked or autosomal dominant pattern. EDMD is characterized by muscle weakness and wasting joint contractures, and cardiac involvement. Option: D. Limb-girdle muscular dystrophy: It (LGMD) is a group of inherited muscle disorders caused by mutations in various genes. LGMD typically affects the proximal muscles of the hips and shoulders, leading to difficulty walking and climbing stairs. LGMD can be inherited in an autosomal dominant or recessive pattern, depending on the subtype.</p>\n<p><strong>Extraedge:</strong></p><p>Feature Myotonic Dystrophy type 1 Myotonic Dystrophy type 2 Genetic cause Expansion of CTG repeat in DMPK gene Expansion of CCTG repeat in CNBP gene Chromosome location 19q13.3 3q21.3-3q24 Onset age Any age, but usually before age 40 Later onset, usually after age 50 Muscles involved Distal and proximal muscles, facial muscles, and muscles involved in swallowing and breathing Mainly proximal muscles Myotonia severity Severe Mild to moderate</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 19 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 16-year-old boy presented to the OPD is brought to the physician by his parents because of a failure to develop normal male secondary sexual characteristics. He is above normal height and weight for his age. Physical examination shows small testes and gynecomastia. His parents report that he had to repeat the 8th and 9th grades and still struggles in his classes. This patient's condition is most likely related to which of the following genetic abnormalities?", "options": [{"label": "A", "text": "Deletion of a gene", "correct": false}, {"label": "B", "text": "Nondisjunction of an autosomal chromosome", "correct": false}, {"label": "C", "text": "Nondisjunction of a sex chromosome", "correct": true}, {"label": "D", "text": "Reciprocal translocation", "correct": false}], "correct_answer": "C. Nondisjunction of a sex chromosome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nondisjunction of a sex chromosome The correct answer is C. The boy probably has Klinefelter syndrome (47, XXY) , which has the typical presentation described in the question. Klinefelter’s syndrome is the most common congenital abnormality causing primary hypogonadism and occurs in approximately 1 in 1000 live births. The diagnosis is commonly made during adolescence or adulthood in males with small testes with hypergonadotropic hypogonadism and gynecomastia . Two common symptoms leading to the diagnosis include infertility and gynecomastia. Other symptoms include fatigue, erectile dysfunction, language impairment, academic difficulty, subnormal libido, osteoporosis, and behavioural problems . Karyotype for a person with Klinefelters :</p>\n<p><strong>Highyeild:</strong></p><p>Genomic imprinting: Preferential expression of genes from either parent. In Prader-Willi syndrome , deletion of band q12 on the long arm of paternal chromosome 15 Genes in this region of maternal chromosome 15 are imprinted, so their functions are entirely lost. Patients have mental retardation, short stature, hypotonia, hyperphagia, small hands and feet, and hypogonadism . In Angelman syndrome, the same region is deleted from the maternal chromosome . Since genes on the corresponding part of paternal chromosome 15 are imprinted, these patients have mental retardation, ataxia, seizures, and inappropriate laughter .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Deletion of a gene. E.g., Prader-Willi and Angelman syndromes, both of which occur on the q arm of chromosome 15 . Both conditions can present with intellectual disability. Prader-Willi syndrome can exhibit uncontrollable appetite and increased weight , whereas Angelman syndrome would exhibit ataxia with constant smiling and laughing (\"happy puppet\") . Option: B. Nondisjunction of an autosomal chromosome. Examples of nondisjunction of autosomes include trisomies, such as most cases of Down syndrome (trisomy 21) , Edwards syndrome (trisomy 18) , and Patau syndrome (trisomy 13) . Option: D. Reciprocal translocation. Reciprocal translocations result when two non-homologous chromosomes exchange genetic material .</p>\n<p><strong>Extraedge:</strong></p><p>Disomy of maternal chromosome is because of the following: Deletion of Paternal chromosomes . Disomy of Paternal chromosomes . Angelman syndrome is because of the following: Deletion of Maternal chromosomes . Disomy of Paternal chromosomes .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is true about the given Image?", "options": [{"label": "A", "text": "Ring chromosome", "correct": false}, {"label": "B", "text": "Isochromosome", "correct": true}, {"label": "C", "text": "Inversion", "correct": false}, {"label": "D", "text": "Deletion", "correct": false}], "correct_answer": "B. Isochromosome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822232627-QTDP031002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Isochromosome Isochromosome formation results when one arm of a chromosome is lost and the remaining arm is duplicated , resulting in a chromosome consisting of only two short arms or two long arms . An Isochromosome has morphologically identical genetic information in both arms . The most common isochromosome present in live births involves the long arm of the X and is designated i(X)(q10).</p>\n<p><strong>Highyeild:</strong></p><p>Epigenetics: Epigenetics is the study of heritable chemical modification of DNA or chromatin that does NOT alter the DNA sequence itself . Examples of such modification include the methylation of DNA and the methylation and acetylation of histones . Epigenetic modifications are critical for normal human development , including the regulation of tissue-specific gene expression , X chromosome inactivation , and imprinting , as well as for understanding the cellular perturbations in aging and cancer. Gene expression frequently correlates negatively with the level of methylation of DNA . Methylation analysis is also essential in diagnosing Prader-Willi syndrome and Angelman syndrome. MNEMONIC: M ethylation M utes</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Ring chromosome. A ring chromosome is a special form of deletion . It is produced when a break occurs at both ends of a chromosome with fusion of the damaged ends . If significant genetic material is lost, phenotypic abnormalities result. Option: C. Inversis a rearrangement involving two breaks within a single chromosome with reincorporation of the inverted, intervening segment . An inversion involving only one arm of the chromosome is known as paracentric . If the breaks are on opposite sides of the centromere, it is known as pericentric . Option: D. Deletion refers to the loss of a portion of a chromosome . Most deletions are interstitial, but rarely terminal deletions may occur. Interstitial deletions occur when there are two breaks within a chromosome arm, followed by loss of the chromosomal material between the breaks and fusion of the broken ends.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is a key pathological feature of myasthenia gravis?", "options": [{"label": "A", "text": "Neuronal loss in the spinal cord", "correct": false}, {"label": "B", "text": "Neuromuscular junction destruction", "correct": true}, {"label": "C", "text": "Cerebral cortical atrophy", "correct": false}, {"label": "D", "text": "White matter demyelination", "correct": false}], "correct_answer": "B. Neuromuscular junction destruction", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neuromuscular junction destruction Myasthenia gravis is an autoimmune disorder in which antibodies attack the acetylcholine receptors (AChR) at the neuromuscular junction, leading to their destruction and impaired neuromuscular transmission.</p>\n<p><strong>Highyeild:</strong></p><p>Myasthenia Gravis It is an autoimmune disorder characterized by muscle weakness and fatigue. Cause: Autoantibodies that bind to acetylcholine receptors (AChR) at the neuromuscular junction. Features: The most common clinical presentation is the weakness of the ocular muscles, leading to ptosis and diplopia . Weakness of the bulbar muscles, leading to dysarthria, dysphagia, and respiratory distress. Associated with thymic abnormalities in up to 80% of patients, including thymoma, thymic hyperplasia, or thymic involution. Myasthenic crisis is a life-threatening condition characterized by respiratory muscle weakness and requires prompt recognition and intervention. Treatment: Acetylcholinesterase inhibitors, immunosuppressive drugs, plasmapheresis, and thymectomy.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Neuronal loss in the spinal cord: It is not a key pathological feature of myasthenia gravis. Myasthenia gravis is an autoimmune disorder that affects the neuromuscular junction, leading to muscle weakness and fatigue. Option: C. Cerebral cortical atrophy: It is not a key pathological feature of myasthenia gravis. Myasthenia gravis is primarily a disorder of the neuromuscular junction. Option: D. White matter demyelination: It is not a key pathological feature of myasthenia gravis. Demyelination is a feature of some other neurological disorders, such as multiple sclerosis.</p>\n<p><strong>Extraedge:</strong></p><p>Most sensitive investigation for Myasthenia Gravis : Single fiber EMG Most specific Investigation for Myasthenia Gravis: Antibodies to acetylcholine receptors (AChR)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is not a characteristic feature of Myelodysplastic syndrome?", "options": [{"label": "A", "text": "Leucoerythroblastic blood picture", "correct": true}, {"label": "B", "text": "Pawn ball megakaryocytes", "correct": false}, {"label": "C", "text": "Pseudo Pelger Huet cells", "correct": false}, {"label": "D", "text": "Transformation to AML", "correct": false}], "correct_answer": "A. Leucoerythroblastic blood picture", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leucoerythroblastic blood picture Myelodysplastic syndrome usually results in pancytopenia rather than leukoerythroblastic blood picture.</p>\n<p><strong>Highyeild:</strong></p><p>Myelodysplastic syndrome (MDS): MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow . Classification: Refractory Cytopenia of Unilineage Dysplasia Refractory Cytopenia of Multilineage Dysplasia Refractory Anemia with Ring Sideroblasts Refractory Anemia with Excess Blasts MDS with isolated 5q deletions Characteristic changes were seen in MDS in different lineages: Erythroid lineage Ring erythroblast and sideroblast Dimorphic RBCs Bone marrow: Erythroid hyperplasia with nuclear budding and bridging Granulocytic lineage Dohle bodies Pseudo pegler huet anomaly Megakaryocytic lineage Giant platelets Pawn ball megakaryocyte Most common cytogenetic abnormality in MDS: 5q deletion Hallmark genetic abnormality: Loss of RPS 14 All types of MDS can progress to AML but increased incidence with therapy-related MDS (t-MDS) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Pawn ball megakaryocytes. Correct . Option: C. Pseudo pelger huet cells. Correct . Option: D. Transformation to AML. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pseudo-Pelger-Huet cells are seen in-", "options": [{"label": "A", "text": "Myelodysplastic syndrome", "correct": false}, {"label": "B", "text": "Accelerated phase of CML", "correct": false}, {"label": "C", "text": "AML with dysplastic maturation", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Pseudo-Pelger-Hüet neutrophils: bilobed hypo-granular dysplastic neutrophils seen in Myelodysplastic syndromes (MDS), Accelerated phase of CML, AML with dysplastic maturation . Pseudo-Pelger-Hüet cells, neutrophils with only two nuclear lobes instead of the normal three to four, are observed at the top and bottom of this field.</p>\n<p><strong>Highyeild:</strong></p><p>Myelodysplastic syndrome (MDS): MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow . Classification: Refractory Cytopenia of Unilineage Dysplasia Refractory Cytopenia of Multilineage Dysplasia Refractory Anemia with Ring Sideroblasts Refractory Anemia with Excess Blasts MDS with isolated 5q deletions</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Myelodysplastic syndrome. Correct . Option: B. Accelerated phase of CML. Correct . Option: C. AML with dysplastic maturation. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Characteristic changes were seen in MDS in different lineages: Erythroid lineage Ring erythoblast and sideroblast Dimorphic RBCs Bone marrow: Erythroid hyperplasia with nuclear budding and bridging Granulocytic lineage Dohle bodies Pseudo pegler huet anomaly Megakaryocytic lineage Giant platelets Pawn ball megakaryocyte Most common cytogenetic abnormality in MDS: 5q deletion Hallmark genetic abnormality: Loss of RPS 14 All types of MDS can progress to AML but increased incidence with therapy-related MDS (t-MDS) .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In myelodysplastic syndrome, ring sideroblast is seen in:", "options": [{"label": "A", "text": "Mitochondria", "correct": true}, {"label": "B", "text": "Golgi body", "correct": false}, {"label": "C", "text": "Nuclear membrane", "correct": false}, {"label": "D", "text": "ER", "correct": false}], "correct_answer": "A. Mitochondria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mitochondria In myelodysplastic syndrome, ring sideroblast is seen in Mitochondria Within the erythroid series, common abnormalities include ring sideroblasts and erythroblasts with iron-laden mitochondria visible as perinuclear granules in Prussian blue –stained aspirates or biopsies.</p>\n<p><strong>Highyeild:</strong></p><p>Myelodysplastic syndrome (MDS): MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow . Classification: Refractory Cytopenia of Unilineage Dysplasia Refractory Cytopenia of Multilineage Dysplasia Refractory Anemia with Ring Sideroblasts Refractory Anemia with Excess Blasts MDS with isolated 5q deletions Characteristic changes were seen in MDS in different lineages: Erythroid lineage Ring erythroblast and sideroblast Dimorphic RBCs Bone marrow: Erythroid hyperplasia with nuclear budding and bridging Granulocytic lineage Dohle bodies Pseudo pegler huet anomaly Megakaryocytic lineage Giant platelets Pawn ball megakaryocyte Most common cytogenetic abnormality in MDS: 5q deletion Hallmark genetic abnormality: Loss of RPS 14 All types of MDS can progress to AML but increased incidence with therapy-related MDS (t-MDS) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Golgi body. Incorrect . Option: C. Nuclear membrane. Incorrect . Option: D. ER. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not compatible with a diagnosis of juvenile myelomonocytic leukaemia -", "options": [{"label": "A", "text": "Peripheral blood monocytosis, more than ≥1 × 10^9/L", "correct": false}, {"label": "B", "text": "Increased haemoglobin F levels for age", "correct": false}, {"label": "C", "text": "Presence of BCR-ABL fusion gene", "correct": true}, {"label": "D", "text": "GM-CSF hypersensitivity of myeloid progenitors in vitro", "correct": false}], "correct_answer": "C. Presence of BCR-ABL fusion gene", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Presence of BCR-ABL fusion gene The presence of BCR-ABL fusion gene is not compatible with a diagnosis of juvenile myelomonocytic leukaemia (JMML) The Philadelphia chromosome is seen in CML & some cases of ALL.</p>\n<p><strong>Highyeild:</strong></p><p>MPN-MDS overlap: Chronic Myelomonocytic Leukaemia (CMML) Atypical Chronic Myeloid Leukaemia (aCML): BCR-ABL negative Juvenile Myelomonocytic Leukaemia (JMML) MDS/MPN with ring sideroblasts and thrombocytosis (MPN/MDS-RS-T) MDS/MPN unclassified</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Peripheral blood monocytosis, more than ≥1 × 10^9/L. Correct . Option: B. Increased haemoglobin F levels for age. Correct . Option: D. GM-CSF hypersensitivity of myeloid progenitors in vitro. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Juvenile Myelomonocytic Leukaemia (JMML): JMML is primarily a disease of early childhood and is included, along with CMML, in the “MDS/MPN” WHO category. Both CMML and JMML feature leukocytosis , monocytosis , and hepatosplenomegaly . Additional characteristic features in JMML include thrombocytopenia and elevated fetal haemoglobin . Myeloid progenitors in JMML display GM-CSF hypersensitivity that has been attributed to dysregulated RAS/MAPK signalling. 2016 revised WHO diagnostic criteria for JMML requires the presence of peripheral blood monocyte count ≥1 × 10^9/L , < 20% blasts in blood or BM , splenomegaly , and absence of BCR-ABL1</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is the most common cytogenetic abnormality in adult myelodysplastic syndrome(MDS) -", "options": [{"label": "A", "text": "Trisomy 8", "correct": false}, {"label": "B", "text": "20q-", "correct": false}, {"label": "C", "text": "5q-", "correct": true}, {"label": "D", "text": "Monosomy 7", "correct": false}], "correct_answer": "C. 5q-", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>5q- The cytogenetic anomalies in MDS include deletion (5q) , most common -7, +8, -5 and -18 as the most frequent changes, in the order shown.</p>\n<p><strong>Highyeild:</strong></p><p>Myelodysplastic syndrome (MDS): MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow . Classification: Refractory Cytopenia of Unilineage Dysplasia Refractory Cytopenia of Multilineage Dysplasia Refractory Anemia with Ring Sideroblasts Refractory Anemia with Excess Blasts MDS with isolated 5q deletions Characteristic changes were seen in MDS in different lineages: Erythroid lineage Ring erythroblast and sideroblast Dimorphic RBCs Bone marrow: Erythroid hyperplasia with nuclear budding and bridging Granulocytic lineage Dohle bodies Pseudo pegler huet anomaly Megakaryocytic lineage Giant platelets Pawn ball megakaryocyte Most common cytogenetic abnormality in MDS: 5q deletion Hallmark genetic abnormality: Loss of RPS 14 All types of MDS can progress to AML but increased incidence with therapy-related MDS (t-MDS) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Trisomy 8. Incorrect . Option: B. 20q-. Incorrect . Option: D. Monosomy 7. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "What percentage of hepatocytes are involved in steatosis to be called pathological steatosis?", "options": [{"label": "A", "text": "5 percent", "correct": true}, {"label": "B", "text": "10 percent", "correct": false}, {"label": "C", "text": "25 percent", "correct": false}, {"label": "D", "text": "50 percent", "correct": false}], "correct_answer": "A. 5 percent", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>5 percent Pathologic steatosis is defined as involving more than 5% of hepatocytes.</p>\n<p><strong>Highyeild:</strong></p><p>Steatosis: It is the accumulation of excess fat within hepatocytes. (>5% of hepatocytes) Cause : Alcohol consumption, Obesity, Insulin resistance , and Certain medications. Steatosis can progress to non-alcoholic steatohepatitis (NASH), which is a more severe form of liver disease characterized by inflammation and damage to the liver tissue. Diagnosis: Liver biopsy</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "NAFLD overlaps with alcoholic hepatitis in all of the following features except:", "options": [{"label": "A", "text": "Predominantly lymphocytic infiltrate", "correct": true}, {"label": "B", "text": "Mallory Denk bodies", "correct": false}, {"label": "C", "text": "Steatofibrosis", "correct": false}, {"label": "D", "text": "portal fibrosis", "correct": false}], "correct_answer": "A. Predominantly lymphocytic infiltrate", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Predominantly lymphocytic infiltrate NASH almost completely overlaps in its histologic features with alcoholic hepatitis. However, the predominant type of inflammatory infiltrate is different. In alcoholic hepatitis , the inflammatory infiltrate is predominantly composed of neutrophils , whereas in NASH, mononuclear cells are more prominent.</p>\n<p><strong>Highyeild:</strong></p><p>NASH- Non-alcoholic steatohepatitis NASH is a type of non-alcoholic fatty liver disease (NAFLD) characterized by inflammation and damage to liver tissue, which can lead to fibrosis and cirrhosis in some cases. Seen in non-heavy drinkers : who drink <20 grams/day for men 2 drinks and <10 grams/day for women 1 drink Metabolic risk factors: obesity, insulin resistance, type 2 diabetes, and dyslipidemia. Progression: Highly variable, and some individuals may remain stable or improve over time, while others may develop advanced liver disease and complications.</p>\n<p><strong>Extraedge:</strong></p><p>ANI: ALD/NAFLD Index >2.2 = ALD <2.2 = NAFLA</p>\n<p><strong>Table:</strong></p><p>Histopathology of Nonalcoholic Steatohepatitis Steatosis :\n Accumulation of fat within hepatocytes, which may be macrovesicular or\n microvesicular. Lobular\n inflammation: Inflammatory cells ( mainly\n macrophages ) are in the liver lobules. Ballooning\n degeneration : Enlargement and degeneration\n of hepatocytes with disruption of cytoplasmic architecture. Perisinusoidal\n fibrosis : Accumulation of fibrous tissue around the blood vessels in the\n liver. Mallory-Denk\n bodies : Cytoplasmic eosinophilic inclusions within hepatocytes, which are\n composed of damaged intermediate filaments. Fibrosis :\n Scarring of the liver tissue due to excessive deposition of collagen. Hepatocyte\n injury and death : Necrotic or apoptotic\n hepatocytes, which are often seen in areas of inflammation.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following caspases is involved in Necroptosis?", "options": [{"label": "A", "text": "Caspase 8", "correct": false}, {"label": "B", "text": "Caspase 9", "correct": false}, {"label": "C", "text": "Caspase 6", "correct": false}, {"label": "D", "text": "It is not dependent on caspase", "correct": true}], "correct_answer": "D. It is not dependent on caspase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is not dependent on caspase In sharp contrast to apoptosis , the signals leading to necroptosis do not result in caspase activation , and hence it is also sometimes referred to as “caspase-independent” programmed cell death . In Necroptosis , morphological death is by Necrosis but the mechanical pathway is Apoptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterized by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Caspase 8. Initiator caspase of the extrinsic pathway of apoptosis. Option: B. Caspase 9. Initiator caspase of the intrinsic pathway of apoptosis. Option: C. Caspase 6. Executioner caspase.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Necroptosis can be seen in-", "options": [{"label": "A", "text": "Steatohepatitis", "correct": false}, {"label": "B", "text": "Reperfusion injury", "correct": false}, {"label": "C", "text": "Parkinson disease", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Necroptosis is postulated to be an important death pathway both in physiologic and pathologic conditions . Physiologic necroptosis occurs during the formation of the mammalian bone growth plate . In pathologic states , it is associated with cell death in steatohepatitis , acute pancreatitis , ischemia-reperfusion injury , and neurodegenerative diseases such as Parkinson’s disease . Also referred to as “caspase-independent” programmed cell death . In Necroptosis , morphological death is by Necrosis but the mechanical pathway is Apoptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterized by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Steatohepatitis. Correct . Option: B. Reperfusion injury. Correct . Option: C. Parkinson’s disease. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Necroptosis also acts as a backup mechanism in host defence against certain viruses that encode caspase inhibitors (e.g., cytomegalovirus ). MNEMONIC: The examples of Necroptosis can be remembered with the mnemonic- ‘Necroptosis C an be Sh A R P’: Necroptosis seen in CMV, Steatohepatitis, Acute pancreatitis, Reperfusion injury, Parkinson’s</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are involved in Necroptosis?", "options": [{"label": "A", "text": "RIPK 1 and 2", "correct": false}, {"label": "B", "text": "RIPK 2 and 5", "correct": false}, {"label": "C", "text": "RIPK1 and 3", "correct": true}, {"label": "D", "text": "RIPK 4 and 5", "correct": false}], "correct_answer": "C. RIPK1 and 3", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RIPK1 and 3 Necroptosis involves two kinases called receptor-interacting protein kinases 1 and 3 ( RIPK1 and RIPK3 ). Ligation of TNFR1 recruits these kinases into a multi-protein complex, and RIPK3 phosphorylates a cytoplasmic protein called MLKL. In sharp contrast to apoptosis , the signals leading to necroptosis do not result in caspase activation , and hence it is also sometimes referred to as “caspase-independent” programmed cell death . In Necroptosis , morphological death is by Necrosis but the mechanical pathway is Apoptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterized by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. RIPK 1 and 2. Incorrect . Option: B. RIPK 2 and 5. Incorrect . Option: D. RIPK 4 and 5. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is true regarding Necroptosis?", "options": [{"label": "A", "text": "Only pathological", "correct": false}, {"label": "B", "text": "Only physiological", "correct": false}, {"label": "C", "text": "Can be physiological or pathological", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Can be physiological or pathological", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Can be physiological or pathological Necroptosis can be both physiological and pathological . Apoptosis can also be both pathological and physiological . Necrosis is only pathological . Physiologic necroptosis occurs during the formation of the mammalian bone growth plate . In pathologic states , it is associated with cell death in steatohepatitis , acute pancreatitis , ischemia-reperfusion injury , and neurodegenerative diseases such as Parkinson's disease .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Only pathological. Incorrect . Option: B. Only physiological. Incorrect . Option: D. None of the above. Incorrect .</p>\n<p><strong>Table:</strong></p><p>Necroptosis can\n be both physiological and pathological . Apoptosis can also be both pathological and\n physiological . Necrosis is only pathological . MNEMONIC: The\n examples of Necroptosis can be remembered with the mnemonic- ‘Necroptosis\n C an be Sh A R P’: Necroptosis seen in CMV, Steatohepatitis , Acute pancreatitis, Reperfusion injury, Parkinson’s</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the physiological cause of Necroptosis?", "options": [{"label": "A", "text": "Reperfusion injury", "correct": false}, {"label": "B", "text": "Acute pancreatitis", "correct": false}, {"label": "C", "text": "Neurodegenerative diseases", "correct": false}, {"label": "D", "text": "Growth plate of bone", "correct": true}], "correct_answer": "D. Growth plate of bone", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Growth plate of bone Necroptosis can be both physiological and pathological . Physiologic necroptosis occurs during the formation of the mammalian bone growth plate . In pathologic states , it is associated with cell death in steatohepatitis , acute pancreatitis , ischemia-reperfusion injury , and neurodegenerative diseases such as Parkinson's disease .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Reperfusion injury. Pathological necroptosis . Option: B. Acute pancreatitis. Pathological necroptosis . Option: C. Neurodegenerative diseases. Pathological necroptosis .</p>\n<p><strong>Table:</strong></p><p>Necroptosis can be both physiological and pathological . Apoptosis can also be both pathological and physiological . Necrosis is only pathological . MNEMONIC: The examples of Necroptosis can be remembered with the mnemonic- ‘Necroptosis\n C an be Sh A R P’: Necroptosis seen in CMV, Steatohepatitis , Acute pancreatitis, Reperfusion injury,\n Parkinson’s</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding Pyroptosis except:", "options": [{"label": "A", "text": "Apoptosis accompanied by inflammation", "correct": false}, {"label": "B", "text": "Can be induced by microbial products and necrotic cells", "correct": false}, {"label": "C", "text": "Associated with the release of pyrogens", "correct": false}, {"label": "D", "text": "Formation of the apoptosome", "correct": true}], "correct_answer": "D. Formation of the apoptosome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Formation of the apoptosome There is the formation of an Inflammasome in Pyroptosis , while an apoptosome is formed in the intrinsic pathway of apoptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Apoptosis accompanied by inflammation. True for Pyroptosis . Option: B. Can be induced by microbial products and necrotic cells. True for Pyroptosis . Option: C. Associated with the release of pyrogens. True for Pyroptosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following receptors are involved in Pyroptosis?", "options": [{"label": "A", "text": "RIPK 3", "correct": false}, {"label": "B", "text": "MLKL", "correct": false}, {"label": "C", "text": "Toll-like Receptors", "correct": false}, {"label": "D", "text": "NOD-like receptors", "correct": true}], "correct_answer": "D. NOD-like receptors", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NOD-like receptors NOD-like receptors (NLRs) are associated with Pyroptosis which recognizes microbial products and necrotic cells. NLRs signal via a cytosolic multiprotein complex called the inflammasome , which activates Caspase 1 involved in Pyroptosis .</p>\n<p><strong>Highyeild:</strong></p><p>Pyroptosis is a form of apoptosis that is accompanied by the release of the fever-inducing cytokine IL-1 (pyro refers to fever). A complex called Inflammasome is activated when a microorganism enters the host cell and in turn activated caspase-1 (also known as an interleukin-1βconverting enzyme) . Unlike classical apoptosis, this pathway of cell death is characterised by the release of inflammatory mediators .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. RIPK 3. Associated with Necroptosis . Option: B. Associated with Necroptosis . Option: C. Toll-like Receptors. Associated with the innate immune system .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "When neutrophils show a degenerative change in which the nucleus has undergone fragmentation. This process is known as;", "options": [{"label": "A", "text": "Caseous necrosis", "correct": false}, {"label": "B", "text": "Coagulative necrosis", "correct": false}, {"label": "C", "text": "Karyolysis", "correct": false}, {"label": "D", "text": "Karyorrhexis", "correct": true}], "correct_answer": "D. Karyorrhexis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Karyorrhexis Nuclear changes are seen in irreversible cell injury and appear in one of three patterns, all due to the breakdown of DNA: The basophilia of the chromatin may fade Karyolysis Pyknosis is characterized by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation.</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with a detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements Nuclear change s, appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis Pyknosis is characterized by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. With the passage of time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Caseous necrosis. Caseous necrosis is encountered most often in foci of tuberculous infection . The term caseous ( cheese-like ) is derived from the friable white appearance of the area of necrosis . Option: B. Coagulative necrosis. Form of necrosis in which the architecture of dead tissue is preserved for a span of at least some days. The affected tissue has a firm texture (vs Liquefactive necrosis which is characterized by digestion of the dead cells , resulting in the transformation of the tissue into a viscous liquid) . Option: C. The basophilia of the chromatin may fade ie karyolysis , a change that presumably reflects the loss of DNA because of enzymatic degradation by endonucleases .</p>\n<p><strong>Extraedge:</strong></p><p>Neutrophil extracellular traps (NETs) Neutrophil extracellular traps are extracellular fibrillar networks that concentrate antimicrobial substances at sites of infection and trap microbes, helping to prevent their spread. They are produced by neutrophils in response to infectious pathogens ( mainly bacteria and fungi ) and inflammatory mediators (e.g., chemokines, cytokines [mainly interferons], complement proteins, and ROS ). The extracellular traps consist of a viscous meshwork of nuclear chromatin that binds and concentrates granule proteins such as antimicrobial peptides and enzymes. In this process, the nuclei of the neutrophils are lost, leading to the death of the cells . The nuclear chromatin in the NETs , which includes histones and associated DNA, has been postulated to be a source of nuclear antigens in systemic autoimmune diseases , particularly lupus , in which individuals react against their own DNA and nucleoproteins. Neutrophil extracellular traps (NETs). (A) Healthy neutrophils with nuclei stained red and cytoplasm stained green. (B) Release of nuclear material from neutrophils (note that two have lost their nuclei), forming extracellular traps. (C) Electron micrograph of bacteria (staphylococci) trapped in NETs. (From Brinkmann V, Zychlinsky A: Beneficial suicide: why neutrophils die to make NETs, Nat Rev Microbiol 5:577, 2007, with permission.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 67-year-old woman with a past history of myocardial infarction has the lesion seen here grossly in the brain. Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Organizing abscess", "correct": false}, {"label": "B", "text": "Acute meningitis", "correct": false}, {"label": "C", "text": "Liquefactive necrosis", "correct": true}, {"label": "D", "text": "Metastatic carcinoma", "correct": false}], "correct_answer": "C. Liquefactive necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812354953-QTDP007002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Liquefactive necrosis Ischaemia in all solid organs leads to Coagulative necrosis except in CNS which leads to liquefactive necrosis . Liquefactive necrosis is also seen in superimposed bacterial infections . Liquefactive necrosis , in contrast to coagulative necrosis, is characterized by the digestion of dead cells, resulting in the transformation of the tissue into a viscous liquid . The necrotic material is frequently creamy yellow because of the presence of leukocytes and is called pus . For unknown reasons, hypoxic death of cells within the central nervous system often manifests as liquefactive necrosis . Eventually, the digested tissue is removed by phagocytes .</p>\n<p><strong>Highyeild:</strong></p><p>In chronic passive hepatic congestion, as seen in Congestive heart failure, chronic hypoxia may result in ischemic tissue injury and scarring . The centrilobular regions are grossly red-brown and slightly depressed (because of cell death) and are accentuated against the surrounding zones of the uncongested tan liver called nutmeg liver . Microscopically, there is centrilobular congestion and haemorrhage, hemosiderin-laden macrophages, and variable degrees of hepatocyte dropout and necrosis Liver with chronic passive congestion and hemorrhagic necrosis. (A) Central areas are red and slightly depressed compared with the surrounding tan viable parenchyma, forming a \"nutmeg liver\" pattern (so-called because it resembles the cut surface of a nutmeg). (B) Centrilobular necrosis with degenerating hepatocytes and hemorrhage. (Courtesy Dr. James Crawford, Department of Pathology, University of Florida, Gainesville, Fla.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Organizing abscess. Past history of myocardial infarction suggests a thrombo-embolic disorder , there is also no history of fever, headache , or any localising signs thus making abscess unlikely . Option: B. Acute meningitis. History is not suggestive of meningitis, there is no history of high fever, neck rigidity, altered mental status etc, thus making meningitis unlikely. Also, meningitis doesn’t cause a focal lesion in the brain parenchyma . Option: D. Metastatic carcinoma. There is no history of any cancer mentioned in the question making metastatic cancer unlikely.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Necrosis means", "options": [{"label": "A", "text": "Efflux of calcium", "correct": false}, {"label": "B", "text": "Swelling of cell", "correct": false}, {"label": "C", "text": "Enzymatic degradation", "correct": true}, {"label": "D", "text": "Fat deposition", "correct": false}], "correct_answer": "C. Enzymatic degradation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Enzymatic degradation Necrosis is the type of cell death that is associated with loss of membrane integrity and leakage of cellular contents culminating in the dissolution of cells , largely resulting from the degradative action of enzyme s on lethally injured cells. Therefore necrosis means enzyme degradation .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Efflux of calcium. In necrosis there is ATP depletion which causes failure of the Na-K ATPase pump , this results in an increase in Na and Ca inside the cell , thus Ca is increased inside the cell, and effluent is not seen. Option: B. Swelling of the cell. Seen in necrosis , but is not specific to necrosis. Enzymatic degradation better describes necrosis . Option: D. Fat deposition. Seen in Fat necrosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Fibrinoid necrosis may be observed in all of the following except:", "options": [{"label": "A", "text": "Malignant hypertension", "correct": false}, {"label": "B", "text": "Polyarteritis nodosa", "correct": false}, {"label": "C", "text": "Diabetic glomerulosclerosis", "correct": true}, {"label": "D", "text": "Aschoff’s nodule", "correct": false}], "correct_answer": "C. Diabetic glomerulosclerosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Diabetic glomerulosclerosis Fibrinoid necrosis is a special form of necrosis , visible by light microscopy, usually in immune reactions in which complexes of antigens and antibodies are deposited in the walls of arteries . The deposited immune complexes , together with fibrin that has leaked out of vessels , produce a bright pink and amorphous appearance on H & E preparations called fibrinoid. Fibrinoid necrosis is seen in:- Malignant hypertension Vasculitis like polyarteritis nodosa Immune complex deposition (eg: Acute rheumatic fever -Aschoff’s nodule) Fibrinoid necrosis in an artery. The wall of the artery shows a circumferential bright pink area of necrosis with inflammation (neutrophils with dark nuclei).</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Malignant hypertension . Example of Fibrinoid necrosis . Option: B. Polyarteritis nodosa . Example of Fibrinoid necrosis . Option: C. Diabetic glomerulosclerosis . Example of Fibrinoid necrosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 34 years old man comes to medicine OPD with complaints of fever, chest pain, cough, shivering, foul smelling cough, lethargy, and shortness of breath. His blood pressure is 130/80 mmHg, pulse rate is 90/min. A chest X-ray was done which is given below. What type of necrosis is seen in this pathology?", "options": [{"label": "A", "text": "Coagulative necrosis", "correct": false}, {"label": "B", "text": "Liquefactive necrosis", "correct": true}, {"label": "C", "text": "Fibrinoid necrosis", "correct": false}, {"label": "D", "text": "Fat necrosis", "correct": false}], "correct_answer": "B. Liquefactive necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812371858-QTDP007005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Liquefactive necrosis From history and chest x-ray diagnosis of lung abscess is made. There is pus present in an abscess. It is a liquefactive necrosis . It is characterized by the digestion of dead cells , resulting in the transformation of the tissue into a liquid viscous mass . It is seen in focal bacterial or, occasionally, fungal infections because microbes stimulate the accumulation of leukocytes and the liberation of enzymes from these cells. The necrotic material is frequently creamy yellow because of the presence of dead leukocytes and is called pus . For unknown reasons, hypoxic death of cells within the central nervous system often manifests as liquefactive necrosis .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Coagulative necrosis. Coagulative necrosis is a form of necrosis in which the architecture of dead tissues is preserved for a span of at least some days. The affected tissues exhibit a firm texture . Option: C. Fibrinoid necrosis. Fibrinoid necrosis is limited to small blood vessels . Typically, it involves small arteries, arterioles, and glomeruli affected by autoimmune diseases (e.g., systemic lupus erythematosus) or malignant hypertension. Option: D. Fat necrosis . It is seen in breast, pancreas, and buttocks injuries.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about given agarose gel electrophoresis except?", "options": [{"label": "A", "text": "A is the control", "correct": false}, {"label": "B", "text": "The process represented by B is important in embryogenesis and protection from cancer", "correct": false}, {"label": "C", "text": "Inflammation is absent in C", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812372090-QTDP007006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above The given image shows gel electrophoresis where: A= Control B= Stepladder pattern due to Apoptosis C= smear pattern due to Necrosis</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. A is controlled. True Option: B. The process represented by B is important in embryogenesis and protection from cancer. True Option: C. Inflammation is absent in C. False because inflammation is present in necrosis . Option: D. All of the above are true. All of the above are not true .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Ramnath is a 62 years old village man. He is a chronic smoker, For a long time, he was suffering from hypertension and diabetes mellitus. Despite being warned many times by doctors and his family members he never took regular treatment. One night he suddenly developed severe chest pain. He somehow reached the hospital. ECG was done. In ECG there was classical ST elevation in V1-V4 of more than 3 mm with T wave inversion. Diagnosis of anterior wall MI was made. Due to the unavailability of a cath lab, thrombolysis was performed. But after the treatment, the condition of the patient had worsened. In ECG there was no arrhythmia. There was more necrosis of myocytes than it was before thrombolysis. What could be the cause?", "options": [{"label": "A", "text": "Myocardial reperfusion injury", "correct": true}, {"label": "B", "text": "Dressler syndrome", "correct": false}, {"label": "C", "text": "Anaphylaxis to the thrombolytic agent", "correct": false}, {"label": "D", "text": "Patient had Takotsubo cardiomyopathy", "correct": false}], "correct_answer": "A. Myocardial reperfusion injury", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myocardial reperfusion injury Ischemia-Reperfusion Injury : Restoration of blood flow to ischemic tissues can promote recovery of cells if they are reversibly injured, but can also paradoxically exacerbate the injury and cause cell death . As a consequence, reperfused tissues may sustain the loss of cells in addition to the cells that are irreversibly damaged at the end of ischemia. This process, called ischemia-reperfusion injury , is clinically important because it contributes to tissue damage during myocardial and cerebral infarction and following therapies to restore blood flow .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Dressler syndrome. Dressler syndrome , also known as Postmyocardial infarction syndrome , is a form of secondary pericarditis with or without a pericardial effusion , that occurs as a result of injury to the heart or pericardium it occurs after 2 -3 weeks Option: C. Anaphylaxis to thrombolytic agent. Anaphylaxis to the thrombolytic agent can happen but it is rare. Systemic anaphylaxis is characterized by vascular shock, widespread edema, and difficulty in breathing. Option: D. The patient had Takotsubo cardiomyopathy. In Takotsubo cardiomyopathy there is a history of emotional stress or sympathetic overactivity which causes sudden death in patients. Does not give any information on ECHO.</p>\n<p><strong>Extraedge:</strong></p><p>Factors which contribute to Reperfusion injury include Mitochondrial dysfunction Myocyte hyper contracture Free radical Leukocyte aggregation Platelet and complement activation Takotsubo Cardiomyopathy: An increase in catecholamines causes infundibular narrowing Mid and Apical hypokinesia is seen with Basal hyperkinesia ECG: Non-evolving, transient changes in T wave and ST segment Troponin is elevated but Angiogram is normal Treatment: Supportive therapy, Beta-blockers, ACE Inhibitors</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 52-year-old man presents with severe abdominal pain radiating to the back. The patient is a known alcoholic. He is found to have increased serum amylase. On Surgical exploration, the appearance of the resected specimen is as shown below. The most likely pathology is", "options": [{"label": "A", "text": "Coagulative necrosis", "correct": false}, {"label": "B", "text": "Caseous necrosis", "correct": false}, {"label": "C", "text": "Fibrinoid necrosis", "correct": false}, {"label": "D", "text": "Fat necrosis", "correct": true}], "correct_answer": "D. Fat necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812372233-QTDP007008IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fat necrosis The most likely diagnosis is acute pancreatitis with fat necrosis . The areas of white chalky deposits represent foci of fat necrosis with calcium soap formation (saponification) at sites of lipid breakdown in the mesentery. Fat necrosis results from the release of activated pancreatic lipases into the substance of the pancreas and the peritoneal cavity. The fatty acids, so derived, combine with calcium to produce grossly visible chalky-white areas ( fat saponification ). Histologic examination reveals foci of shadowy outlines of necrotic fat cells , with basophilic calcium deposits , surrounded by an inflammatory reaction .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Coagulative necrosis seen in ischemia of solid organs except for CNS . Option: B. Caseous necrosis seen in TB, Syphilis, and Histoplasma . Option: C. Fibrinoid necrosis seen in Vasculitis, Malignant hypertension, and Immune complex deposition .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 55-year-old woman with ischemic heart disease develops congestive heart failure. She also complains of back pain. Urinalysis shows hematuria. Which of the following is the most likely etiology for the gross appearance of the kidney shown here?", "options": [{"label": "A", "text": "Apoptosis", "correct": false}, {"label": "B", "text": "Embolization", "correct": true}, {"label": "C", "text": "Metastasis", "correct": false}, {"label": "D", "text": "HIV infections", "correct": false}], "correct_answer": "B. Embolization", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812373003-QTDP007010IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Embolization The above image shows a wedge-shaped infarction in the kidney. The most common cause of infarction in the kidney is thromboembolism , which leads to the blockage of the blood supply. Past history of myocardial infarction suggests a thromboembolic disorder . The pattern of ischemic necrosis in the kidney is coagulative necrosis .</p>\n<p><strong>Highyeild:</strong></p><p>In chronic passive hepatic congestion, seen in Congestive heart failure, chronic hypoxia may result in ischemic tissue injury and scarring . The centrilobular regions are grossly red-brown and slightly depressed (because of cell death) and are accentuated against the surrounding zones of the uncongested tan liver called nutmeg liver . Microscopically, there is centrilobular congestion and haemorrhage, hemosiderin-laden macrophages, and variable degrees of hepatocyte dropout and necrosis Liver with chronic passive congestion and hemorrhagic necrosis. (A) Central areas are red and slightly depressed compared with the surrounding tan viable parenchyma, forming a \"nutmeg liver\" pattern (so-called because it resembles the cut surface of a nutmeg). (B) Centrilobular necrosis with degenerating hepatocytes and hemorrhage. (Courtesy Dr. James Crawford, Department of Pathology, University of Florida, Gainesville, Fla.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. The given comical history is suggestive of the thromboembolic event causing coagulative necrosis in the kidney , thus it can not be apoptosis. Option: C. There is no history of any cancer mentioned in the question making metastatic cancer unlikely. Option: D. HIV infections. There is no history of any immunocompromised status mentioned in the question making HIV infection unlikely.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 58-year-old man experienced chest pain 4 days ago. He now has increasing dyspnea and an irregular pulse. The representative gross appearance of his interventricular myocardium is shown here. Which of the following microscopic changes is most likely to be present in this condition?", "options": [{"label": "A", "text": "Liquefactive necrosis", "correct": false}, {"label": "B", "text": "Caseous necrosis", "correct": false}, {"label": "C", "text": "Wet gangrene", "correct": false}, {"label": "D", "text": "Coagulative necrosis", "correct": true}], "correct_answer": "D. Coagulative necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812373618-QTDP007011IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Coagulative necrosis The above image shows myocardial infarction , which is characterized by coagulative necrosis . Examples of coagulative necrosis: Ischemic injury in all organs, except the CNS, and Dry gangrene .</p>\n<p><strong>Highyeild:</strong></p><p>In chronic passive hepatic congestion, seen in Congestive heart failure, chronic hypoxia may result in ischemic tissue injury and scarring . The centrilobular regions are grossly red-brown and slightly depressed (because of cell death) and are accentuated against the surrounding zones of the uncongested tan liver called nutmeg liver . Microscopically, there is centrilobular congestion and haemorrhage, hemosiderin-laden macrophages, and variable degrees of hepatocyte dropout and necrosis Liver with chronic passive congestion and hemorrhagic necrosis. (A) Central areas are red and slightly depressed compared with the surrounding tan viable parenchyma, forming a \"nutmeg liver\" pattern (so-called because it resembles the cut surface of a nutmeg). (B) Centrilobular necrosis with degenerating hepatocytes and hemorrhage. (Courtesy Dr. James Crawford, Department of Pathology, University of Florida, Gainesville, Fla.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Liquefactive necrosis. Seen in Ischemia to the brain, Coagulative necrosis with superimposed bacterial infection (Wet Gangrene) . Option: B. Caseous necrosis. Seen in TB, Syphilis and Histoplasma Option: C. Wet gangrene. Refers to Coagulative necrosis with superimposed bacterial infection ie Liquefactive necrosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Coagulative necrosis is seen in all except?", "options": [{"label": "A", "text": "TB", "correct": false}, {"label": "B", "text": "Zenker’s degeneration", "correct": false}, {"label": "C", "text": "Sarcoidosis", "correct": true}, {"label": "D", "text": "Dry gangrene", "correct": false}], "correct_answer": "C. Sarcoidosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Sarcoidosis IN SARCOIDOSIS- Non-caseating granulomas are the typical histological finding in sarcoidosis, in some cases granulomas can undergo caseation, which means they become necrotic and appear as cheesy or caseous material. This is more commonly associated with infections like tuberculosis Microscopically, this necrotic material appears as amorphous, structureless, eosinophilic, granular debris, with a complete loss of cellular details. The granulomas in Crohn’s disease, sarcoidosis, and foreign body reactions tend to not have necrotic centres and are said to be non-caseating.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A biopsy from the brain of a patient who died of high fever, neck rigidity and epilepsy in the last 5 days shows the following. What is your diagnosis?", "options": [{"label": "A", "text": "Gangrenous necrosis", "correct": false}, {"label": "B", "text": "Liquefactive necrosis", "correct": true}, {"label": "C", "text": "Coagulative necrosis", "correct": false}, {"label": "D", "text": "Fibrinoid necrosis", "correct": false}], "correct_answer": "B. Liquefactive necrosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812374472-QTDP007014IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Liquefactive necrosis History is suggestive of Brain abscess . Ischaemia in all solid organs leads to Coagulative necrosis except in CNS which leads to liquefactive necrosis . Liquefactive necrosis is also seen in superimposed bacterial infections . Liquefactive necrosis , in contrast to coagulative necrosis, is characterized by the digestion of dead cells, resulting in the transformation of the tissue into a viscous liquid . The necrotic material is frequently creamy yellow because of the presence of leukocytes and is called pus . For unknown reasons, hypoxic death of cells within the central nervous system often manifests as liquefactive necrosis . Eventually, the digested tissue is removed by phagocytes .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Gangrenous necrosis. Dry gangrene refers to Coagulative necrosis , a clinical term used mainly for ischemia to limbs. Option: B. Coagulative necrosis. Seen in ischemia to solid organs. Option: D: Fibrinoid necrosis was seen in Vasculitis, Malignant hypertension, and Immune complex deposition .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statement is/are true regarding the condition shown below?", "options": [{"label": "A", "text": "Bright pink colour results from immune complexes, together with fibrin that has leaked out of vessel", "correct": false}, {"label": "B", "text": "It appears as bright pink and amorphous on light microscopy in the H&E stain", "correct": false}, {"label": "C", "text": "Seen in immunologically mediated vasculitis", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812375030-QTDP007015IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Fibrinoid necrosis is a special form of necrosis usually seen in immune reactions involving blood vessels. This pattern of necrosis typically occurs when complexes of antigens and antibodies are deposited in the walls of arteries . Deposits of these ‘immune complexes’, together with fibrin that has leaked out of vessels, result in a bright pink and amorphous appearance on H & E stains , called ‘fibrinoid’ (fibrin-like) by pathologists. It is seen in immunologically mediated vasculitis . Fibrinoid necrosis is seen in:- Malignant hypertension Vasculitis like polyarteritis nodosa Immune complex deposition (eg: Acute rheumatic fever -Aschoff’s nodule) Fibrinoid necrosis in an artery. The wall of the artery shows a circumferential bright pink area of necrosis with inflammation (neutrophils with dark nuclei).</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Bright pink colour results from immune complexes, together with fibrin that has leaked out of vessels. True . Option: B. It appears as bright pink and amorphous on light microscopy in H&E stain. True . Option: C. Seen in immunologically mediated vasculitis. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of these shows an acute inflammatory response?", "options": [{"label": "A", "text": "Pyroptosis", "correct": false}, {"label": "B", "text": "Necroptosis", "correct": false}, {"label": "C", "text": "Necrosis", "correct": true}, {"label": "D", "text": "Apoptosis", "correct": false}], "correct_answer": "C. Necrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Necrosis The morphologic appearance of necrosis as well as necroptosis is the result of the denaturation of intracellular proteins and enzymatic digestion of the lethally injured cell . Necrotic cells are unable to maintain membrane integrity and their contents often leak out , a process that may elicit inflammation in the surrounding tissue .</p>\n<p><strong>Highyeild:</strong></p><p>In Apoptosis: The plasma membrane stays intact DNA Electrophoresis shows a Step Ladder pattern In Necrosis: The plasma membrane is disrupted DNA Electrophoresis shows a Smear pattern Features of Necrosis and Apoptosis Feature Necrosis Apoptosis Cell size Enlarged (swelling) Reduced (shrinkage) Nucleus Pyknosis, karyorrhexis, karyolysis Fragmentation into nucleosome-size fragments Plasma membrane Disrupted Intact; altered structure, especially orientation of lipids Cellular contents Enzymatic digestion; may leak out of cell Intact; may be released in apoptotic bodies Adjacent inflammation Frequent No Physiologic or pathologic role Usually pathologic (culmination of irreversible cell injury) Often physiologic, means of eliminating unwanted cells; may be pathologic after some forms of cell injury, especially DNA damage</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Pyrogens (fever-causing mediators like IL-1 ) cause apoptosis. A complex called Inflammasome is activated when a microorganism enters the host cell and in turn, activated caspase 1 . Option: B. Morphological death by Necrosis , Mechanical pathway of initiation by Apoptosis . Option: D. Programmed cell death , is not associated with inflammation. NOTE: Among the above options maximum inflammation is a feature of Necrosis so it is the best answer here. However, Pyroptosis, Necroptosis, and Necrosis all show inflammation .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 24 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Choristoma is a:", "options": [{"label": "A", "text": "Heterotopic (ectopic) rest of cells", "correct": true}, {"label": "B", "text": "Example of hamartoma", "correct": false}, {"label": "C", "text": "Benign tumor of trophoblastic cell", "correct": false}, {"label": "D", "text": "Benign tumor of cartilaginous tissue", "correct": false}], "correct_answer": "A. Heterotopic (ectopic) rest of cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Heterotopic (ectopic) rest of cells Choristoma is the term applied to a heterotopic (misplaced) rest of cells . For example, a small nodule of well-developed and normally organized pancreatic tissue may be found in the submucosa of the stomach, duodenum, or small intestine.</p>\n<p><strong>Highyeild:</strong></p><p>Choristoma: Normal tissue at abnormal site, eg: Normal Gastric mucosa in pancreatic biopsy . Hamartoma: Abnormal tissue at normal site, eg: Dysplastic lung tissue in lump .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Example of hamartoma. Incorrect , hamartoma is abnormal tissue at normal site . Option: C. Benign tumor of trophoblastic cell. Incorrect , Hydatidiform mole or molar pregnancy is benign tumor of trophoblastic cell . Option: D. Benign tumor of cartilaginous tissue. Incorrect , Chondroma is benign tumor of cartilaginous tissue .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Lack of differentiation is called:", "options": [{"label": "A", "text": "Anaplasia", "correct": true}, {"label": "B", "text": "Metaplasia", "correct": false}, {"label": "C", "text": "Dysplasia", "correct": false}, {"label": "D", "text": "Carcinoma in situ", "correct": false}], "correct_answer": "A. Anaplasia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anaplasia</p>\n<p><strong>Highyeild:</strong></p><p>Differentiation refers to the extent to which neoplastic parenchymal cells resemble the corresponding normal parenchymal cells , both morphologically and functionally; lack of differentiation is called anaplasia . In general, benign tumors are well differentiated .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Metaplasia is defined as the replacement of one type of cell with another type . Metaplasia is nearly always found in association with tissue damage, repair, and regeneration . Option: C. Dysplasia is a term that literally means “ disordered growth .” Dysplastic epithelial surfaces also typically show architectural disarray and a loss of orderly differentiation . Option: D. Carcinoma in situ. When dysplasia is severe and involves the full thickness of the epithelium but the lesion does not penetrate the basement membrane , it is referred to as carcinoma in situ .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following features of nephrotic syndrome except:", "options": [{"label": "A", "text": "Proteinuria", "correct": false}, {"label": "B", "text": "Hypoalbuminemia", "correct": false}, {"label": "C", "text": "Hyperlipidemia", "correct": false}, {"label": "D", "text": "Hematuria", "correct": true}], "correct_answer": "D. Hematuria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hematuria Hematuria is not a feature of nephrotic syndrome . It is typically seen in glomerular diseases that involve inflammation or damage to the glomerular capillaries, such as IgA nephropathy, lupus nephritis, or rapidly progressive glomerulonephritis. However, it is not a common feature of nephrotic syndrome, which is primarily characterized by proteinuria and hypoalbuminemia.</p>\n<p><strong>Highyeild:</strong></p><p>Nephrotic syndrome It is caused by a derangement in glomerular capillary walls resulting in increased permeability to plasma proteins. The manifestations of the syndrome include: Massive proteinuria, with the daily loss of 3.5 gm or more of protein (less in children) Hypoalbuminemia , with plasma albumin levels less than 3 gm/dL Generalized edema Hyperlipidemia and lipiduria Associated with the hypercoagulable state due to antithrombin III loss in urine Increased risk of infection</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Proteinuria: This is a hallmark feature of nephrotic syndrome, with proteinuria typically exceeding 3.5 grams per day. Option: B. Hypoalbuminemia: This is a common feature of nephrotic syndrome, with serum albumin levels typically falling below 3.0 grams per deciliter. Option: C. Hyperlipidemia: This is another hallmark feature of nephrotic syndrome, with elevated levels of cholesterol, triglycerides, and other lipids in the blood. This occurs as a compensatory mechanism to replace the lost proteins, particularly albumin, which binds to and transports lipids.</p>\n<p><strong>Extraedge:</strong></p><p>Nephrotic syndrome Vs Nephritic syndrome Characteristics Nephrotic syndrome Nephritic syndrome Pathophysiology Damage to the foot process of podocyte Disruption of glomerular basement membrane due to inflammation Urine protein >3.5g/day <3.5g/day Hematuria Mild or absent Present Hypertension Mild or absent Often present Edema Present Often absent Serum Albumin <3.0g/dL Normal or decreased Serum creatinine Normal or decreased Increase Serum sodium Normal or decreased Normal or decreased Urine Sediment Few cells, fatty casts or none Red blood cell casts, cellular debris</p>\n<p><strong>Table:</strong></p><p>Casts in urine Cast type Appearance Associated conditions Hyaline Colo u rless, transparent, homogenous Normal finding, non-specific Red blood cell Red or reddish-brown,\n cylindrical Glomerulonephritis,\n vasculitis, hypertension, neoplasia, anticoagulant therapy White blood cell Variable shape, with granules\n or nuclei visible Pyelonephritis, interstitial\n nephritis, glomerulonephritis, lupus nephritis Granular Coarse or fine, muddy brown in\n appearance Acute tubular necrosis Fatty Round or oval, refractile,\n yellow-brown, with a clear halo Nephrotic syndrome, diabetic\n nephropathy, nephrotoxic drugs Waxy Broad, colourless, homogenous,\n refractile End-stage renal disease Epithelial Squamous cells from the urethra or bladder may have internal debris Nonspecific, may be seen in a\n variety of conditions</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The hypercoagulable state in nephrotic syndrome is due to:", "options": [{"label": "A", "text": "Loss of antithrombin III", "correct": true}, {"label": "B", "text": "Decreased fibrinogen", "correct": false}, {"label": "C", "text": "Decrease metabolism of Vitamins K", "correct": false}, {"label": "D", "text": "Increase in protein C", "correct": false}], "correct_answer": "A. Loss of antithrombin III", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Loss of antithrombin III The hypercoagulable state in nephrotic syndrome is primarily due to the loss of antithrombin III. This loss is due to increased urinary excretion and decreased hepatic synthesis of antithrombin III.</p>\n<p><strong>Highyeild:</strong></p><p>Nephrotic syndrome It is caused by a derangement in glomerular capillary walls resulting in increased permeability to plasma proteins. The manifestations of the syndrome include: Massive proteinuria, with the daily loss of 3.5 gm or more of protein (less in children) Hypoalbuminemia , with plasma albumin levels less than 3 gm/dL Generalized edema Hyperlipidemia and lipiduria Associated with the hypercoagulable state due to antithrombin III loss in urine Increased risk of infection</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Decreased fibrinogen: Fibrinogen is a plasma protein that is involved in the formation of blood clots. Decreased fibrinogen levels would actually decrease the tendency towards clot formation. Option: C. Decreased metabolism of Vitamins K: Vitamin K is necessary for the production of several coagulation factors, including factors II, VII, IX, and X. However, decreased metabolism of vitamin K would not explain the hypercoagulable state seen in nephrotic syndrome. Option: D. Increase in protein C: Protein C is an anticoagulant protein that, when activated, inactivates coagulation factors V and VIII.</p>\n<p><strong>Extraedge:</strong></p><p>Nephrotic syndrome Vs Nephritic syndrome Characteristics Nephrotic syndrome Nephritic syndrome Pathophysiology Damage to the foot process of podocyte Disruption of glomerular basement membrane due to inflammation Urine protein >3.5g/day <3.5g/day Hematuria Mild or absent Present Hypertension Mild or absent Often present Edema Present Often absent Serum Albumin <3.0g/dL Normal or decreased Serum creatinine Normal or decreased Increase Serum sodium Normal or decreased Normal or decreased Urine Sediment Few cells, fatty casts or none Red blood cell casts, cellular debris</p>\n<p><strong>Table:</strong></p><p>Casts in urine Cast type Appearance Associated conditions Hyaline Colo u rless, transparent, homogenous Normal finding, non-specific Red blood cell Red or reddish-brown, cylindrical Glomerulonephritis, vasculitis, hypertension, neoplasia, anticoagulant therapy White blood cell Variable shape, with granules or nuclei visible Pyelonephritis, interstitial nephritis, glomerulonephritis, lupus nephritis Granular Coarse or fine, muddy brown in appearance Acute tubular necrosis Fatty Round or oval, refractile, yellow-brown, with a clear halo Nephrotic syndrome, diabetic nephropathy, nephrotoxic drugs Waxy Broad, colourless, homogenous, refractile End-stage renal disease Epithelial Squamous cells from the urethra or bladder may have internal debris Nonspecific, may be seen in a variety of conditions</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Onion bulb appearance on nerve biopsy is seen in:", "options": [{"label": "A", "text": "Autoimmune neuropathy", "correct": false}, {"label": "B", "text": "Chronic inflammatory demyelinating neuropathy", "correct": true}, {"label": "C", "text": "Vasculitis-associated neuropathy", "correct": false}, {"label": "D", "text": "Toxic neuropathy", "correct": false}], "correct_answer": "B. Chronic inflammatory demyelinating neuropathy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic inflammatory demyelinating neuropathy Onion bulb appearance on nerve biopsy is a characteristic feature of chronic inflammatory demyelinating neuropathy (CIDP). The onion bulb appearance is seen on nerve biopsy due to the presence of multiple concentric layers of Schwann cells around the nerve fibers. This is a result of the process of demyelination and remyelination that occurs in CIDP.</p>\n<p><strong>Highyeild:</strong></p><p>CIDP- Chronic inflammatory demyelinating polyneuropathy It is a chronic, immune-mediated neuropathy that affects peripheral nerves, causing weakness and sensory loss. Presentation: Progressive, symmetric, and proximal muscle weakness with sensory symptoms in a stocking-glove distribution . Diagnosis: Nerve conduction studies and nerve biopsy Treatment: Corticosteroids, intravenous immunoglobulin (IVIG), and plasma exchange.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. Autoimmune neuropathy: Autoimmune neuropathies are a heterogeneous group of disorders characterized by damage to the peripheral nerves due to an autoimmune response. The typical histological findings in autoimmune neuropathy include lymphocytic infiltration, axonal degeneration, and segmental demyelination. Option:C. Vasculitis-associated neuropathy: Vasculitis is a group of disorders characterized by inflammation of the blood vessels. Vasculitis-associated neuropathy can affect both the peripheral and central nervous systems. The typical histological findings in vasculitis-associated neuropathy include perivascular inflammation, fibrinoid necrosis, and leukocytoclastic vasculitis. Option:D. Toxic neuropathy: It is caused by exposure to toxic substances, such as heavy metals, solvents, and drugs. The typical histological findings in toxic neuropathy include axonal degeneration, segmental demyelination, and fiber loss. neuropathy.</p>\n<p><strong>Extraedge:</strong></p><p>Different variants of CIDP Variant Description Typical CIDP Symmetric, progressive, proximal, and distal muscle weakness, and sensory symptoms Atypical CIDP CIDP with atypical features such as asymmetric involvement or more focal presentation Multifocal motor neuropathy (MMN) Purely motor neuropathy with asymmetric weakness and partial conduction block Sensory CIDP CIDP with predominant sensory symptoms Distal acquired demyelinating symmetric neuropathy (DADS) CIDP with predominant distal symptoms Lewis-Sumner syndrome (LSS) Asymmetric or multifocal neuropathy with predominant distal involvement and conduction block Chronic immune sensory polyradiculopathy (CISP) Chronic sensory ataxic neuropathy with anti-GD1b antibodies IgG4-associated neuropathy (IgG4-RD) CIDP-like neuropathy associated with IgG4-related disease</p>\n<p><strong>Table:</strong></p><p>Difference between Myasthenia Gravis and Lambert-Eaton Myasthenic\n Syndrome Characteristics Myasthenia Gravis Lambert-Eaton Myasthenic Syndrome Incidence Most common NMJ disorder Typically occurs in young <40 years old More common in females Uncommon Typically occurs in old >40 years old More common in males Pathophysiology Postsynaptic transmission defect Autoantibodies to postsynaptic ACh\n receptor Presynaptic transmission defect Autoantibodies to pre-synaptic Ca2+\n channels Muscle weakness pattern Weakness worsens with sustained activity EMG on repetitive nerve stimulation shows the decremental response Weakness improves with sustained activity EMG on repetitive nerve stimulation shows\n the incremental response Reflexes Spared reflexes Hyporeflexia Associated conditions Thymus abnormalities present in 75% of patients Associated with small cell lung cancer in 50% of\n patients AChE inhibitor administration Reverses symptoms Minimal effect</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is not true regarding the process of \"NETosis\"?", "options": [{"label": "A", "text": "Causes the death of neutrophils", "correct": false}, {"label": "B", "text": "Chromatin condensation", "correct": true}, {"label": "C", "text": "Detected in blood in patients with sepsis", "correct": false}, {"label": "D", "text": "Plays a role in the pathogenesis of SLE", "correct": false}], "correct_answer": "B. Chromatin condensation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chromatin condensation NETosis , e. the process of formation of Neutrophil Extracellular Traps (NETS): Extracellular fibrillar networks that concentrate antimicrobial substances at sites of infection and trap microbes, helping to prevent their spread . NET formation starts with ROS-dependent activation of an arginine deaminase that converts arginine to citrulline , leading to chromatin decondensation.</p>\n<p><strong>Highyeild:</strong></p><p>Neutrophil extracellular traps (NETs) Neutrophil extracellular traps are extracellular fibrillar networks that concentrate antimicrobial substances at sites of infection and trap microbes, helping to prevent their spread. Neutrophils produce them in response to infectious pathogens ( mainly bacteria and fungi ) and inflammatory mediators (e.g., chemokines, cytokines [mainly interferons], complement proteins, and ROS ). The extracellular traps consist of a dense meshwork of nuclear chromatin that binds and concentrates granule proteins such as antimicrobial peptides and enzymes. In this process, the nuclei of the neutrophils are lost , leading to the death of the cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Causes death of neutrophils. True . Option: C. Detected in blood in patients with sepsis. True . Option: D. Plays a role in the pathogenesis of SLE. True .</p>\n<p><strong>Extraedge:</strong></p><p>The nuclear chromatin in the NETs , which includes histones and associated DNA, has been postulated to be a source of nuclear antigens in systemic autoimmune diseases , particularly lupus , in which individuals react against their DNA and nucleoproteins. Neutrophil extracellular traps (NETs). (A) Healthy neutrophils with nuclei stained red and cytoplasm stained green. (B) Release of nuclear material from neutrophils (note that two have lost their nuclei), forming extracellular traps. (C) Electron micrograph of bacteria (staphylococci) trapped in NETS. (From Brinkmann V, Zychlinsky A: Beneficial suicide: why neutrophils die to make NETs, Nat Rev Microbiol 5:577, 2007, with permission.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Most Common extranodal site of Lymphoma in HIV is?", "options": [{"label": "A", "text": "CNS", "correct": true}, {"label": "B", "text": "GIT", "correct": false}, {"label": "C", "text": "Retroperitoneum", "correct": false}, {"label": "D", "text": "Mediastinum", "correct": false}], "correct_answer": "A. CNS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CNS Most common extranodal site for Lymphoma in: General population: GIT (stomach). HIV patients: CNS .</p>\n<p><strong>Highyeild:</strong></p><p>Lymphoma in HIV 90% of lymphomas in HIV are B cells in phenotype; more than half contain EBV DNA . Immunoblastic lymphomas account for 60% of the cases of lymphoma in patients with AIDS. Primary CNS lymphoma accounts for 20% of the cases of lymphoma in patients with HIV infection . The most common extranodal site involved in Lymphoma in HIV is the CNS, which is involved in one-third of all patients with lymphoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. GIT. The most common extranodal site for Lymphoma in the general population . Option: C. Retroperitoneum. Incorrect . Option: D. Mediastinum. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Neoplastic cells with multilobulated nuclei (cloverleaf or flower cells) are seen in-", "options": [{"label": "A", "text": "Diffuse large B cell lymphoma", "correct": false}, {"label": "B", "text": "Adult T cell leukaemia", "correct": true}, {"label": "C", "text": "Anaplastic large T cell lymphoma", "correct": false}, {"label": "D", "text": "Mycosis fungoides", "correct": false}], "correct_answer": "B. Adult T cell leukaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adult T cell leukaemia Adult T-Cell Leukaemia/Lymphoma This neoplasm of CD4+ T cells is only observed in adults infected by human T-cell leukaemia retrovirus type 1( HTLV-1 ) Common findings include skin lesions, generalized lymphadenopathy, hepatosplenomegaly, peripheral blood lymphocytosis, and hypercalcemia . Tumour cells with multilobulated nuclei (“cloverleaf” or “flower” cells) . Most patients present with a rapidly progressive disease that is fatal within months to 1 year despite aggressive chemotherapy . Less commonly, the tumour involves only the skin and follows a much more indolent course, like that of mycosis fungoides</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Diffuse large B cell lymphoma. Shows a relatively large cell size and a diffuse pattern of growth . Option: C. Anaplastic large T cell lymphoma. Typically composed of large anaplastic cells, with horseshoe-shaped nuclei & voluminous cytoplasm (so-called hallmark cells ). Option: D. Mycosis fungoides. Neoplastic T cells, often have a cerebriform appearance due to marked infolding of the nuclear membrane.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Gastric MALTomas may express all of the following except:", "options": [{"label": "A", "text": "CD5", "correct": true}, {"label": "B", "text": "CD19", "correct": false}, {"label": "C", "text": "CD20", "correct": false}, {"label": "D", "text": "CD43", "correct": false}], "correct_answer": "A. CD5", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD5 Expressed by Mantle zone lymphoma.</p>\n<p><strong>Highyeild:</strong></p><p>Marginal Zone Lymphoma: The category of marginal zone lymphomas encompasses a group of B-cell tumours that arise within lymph nodes, spleen, or extranodal tissues . Extranodal tumours were initially recognized at mucosal sites and are often referred to as mucosa-associated lymphoid tumours (or MALTomas) . In most cases, the tumour cells show evidence of somatic hypermutation and are considered to be of memory B-cell origin . It has three exceptional characteristics. They often arise within tissues involved by chronic inflammatory disorders of autoimmune or infectious etiology ; examples include the salivary gland in Sjögren disease, the thyroid gland in Hashimoto thyroiditis, and the stomach in Helicobacter gastritis. They remain localized for prolonged periods , spreading systemically only late in their course. They may regress if the inciting agent (e.g., H. pylori) is eradicated . MALT lymphomas express B-cell antigens (CD19 and CD20) & monotypic surface Ig (IgM without IgD). MALTomas may be CD43+ but lack other small B-cell lymphoma markers (CD5, CD10, CD23 & cyclin D1).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. CD19. MALTomas are B cell tumours and thus express CD 19 (Pan B cell marker) . Option: C. CD20. MALTomas are B cell tumours and thus express CD 20 (Mature B cell marker) . Option: D. CD43. Expressed by MALTomas.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The Commonest site for extranodal lymphoma is-", "options": [{"label": "A", "text": "Liver", "correct": false}, {"label": "B", "text": "Stomach", "correct": true}, {"label": "C", "text": "Small intestine", "correct": false}, {"label": "D", "text": "Large intestine", "correct": false}], "correct_answer": "B. Stomach", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Stomach The commonest site for extranodal lymphoma is the Stomach The gastrointestinal tract is the most common site for extranodal NHL (10 to 15% of all NHL). The stomach accounts for 50% of gastrointestinal lymphomas 60% of gastric lymphoma are aggressive, usually DLBCL, while 40% are low-grade, usually MALT type.</p>\n<p><strong>Highyeild:</strong></p><p>Most common extranodal site for Lymphoma in: General population: GIT (stomach). HIV patients: CNS . Lymphoma in HIV 90% of lymphomas in HIV are B cells in phenotype; more than half contain EBV DNA centresunoblastic lymphomas accounting for 60% of the cases of lymphoma in patients with AIDS. Primary CNS lymphoma accounts for 20% of the cases of lymphoma in patients with HIV infection . The most common extranodal site involved in Lymphoma in HIV is the CNS, which is involved in one-third of all patients with lymphoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Liver. Incorrect . Option: C. Small intestine. Incorrect . Option: D. Large intestine. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "“Smudge cells” in the peripheral smear are characteristic of-", "options": [{"label": "A", "text": "Chronic myelogenous leukaemia", "correct": false}, {"label": "B", "text": "Chronic lymphocytic leukaemia", "correct": true}, {"label": "C", "text": "Acute myelogenous leukaemia", "correct": false}, {"label": "D", "text": "Acute lymphoblastic leukaemia", "correct": false}], "correct_answer": "B. Chronic lymphocytic leukaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chronic lymphocytic leukaemia “Smudge cells”</p>\n<p><strong>Highyeild:</strong></p><p>Chronic Lymphocytic Leukaemia (CLL)/ Small Lymphocytic Lymphoma (SLL): CLL is the most common leukaemia in adults in the Western world . The median age at diagnosis is 60 years , and there is a 2:1 male predominance . Microscopy: Lymph nodes are diffusely effaced by predominantly small lymphocytes called Pseudofollicular architecture with proliferation centres . Peripheral smear: Smudge cells Caused by a decrease in Vimentin May predict a good prognosis Seen mainly in CLL; Also have been reported in AML, CML, and ALL & the normal peripheral smear, but rare. Chronic lymphocytic leukemia. This peripheral blood smear is flooded with small lymphocytes with condensed chromatin and scant cytoplasm. A characteristic finding is the presence of disrupted tumor cells (smudge cells), two of which are present in this smear. A coexistent autoimmune hemolytic anemia (Chapter 14) explains the presence of spherocytes (hyperchromatic, round erythrocytes). A nucleated erythroid cell is present in the lower left-hand corner of the field. In this setting, circulating nucleated red cells could stem from premature release of progenitors in the face of severe anemia, marrow infiltration by tumor (leukoerythroblastosis), or both. Mutation: Chromosome 13q deletion Immunohistochemistry: CD5 +, CD23 +, CD19 +, CD 20+ Transformation to diffuse large B-cell lymphoma (DLBCL), is called Richter syndrome .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Chronic myelogenous leukaemia. False, leukocytosis, shift to left and basophilia are seen . Option: C. Acute myelogenous leukaemia. False, Myeloblasts are seen. Option: D. Acute lymphoblastic leukaemia. False, Lymphoblasts are seen.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A patient of 70 years, presented with generalized lymphadenopathy. WBC count was 20,000/mm3 and blood film showed >70% mature-looking lymphocytes. Next investigation that should be done:", "options": [{"label": "A", "text": "LN biopsy", "correct": false}, {"label": "B", "text": "Peripheral blood Immunophenotyping", "correct": true}, {"label": "C", "text": "Bone marrow aspiration", "correct": false}, {"label": "D", "text": "Peripheral blood cytogenetics", "correct": false}], "correct_answer": "B. Peripheral blood Immunophenotyping", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Peripheral blood Immunophenotyping In the given question, an elderly patient with generalized lymphadenopathy was found to have a WBC count of 20,000/mm3 and blood film showed >70% mature-looking lymphocytes i.e. Peripheral smear has been done and is showing leukocytosis, with mature lymphocytes . Most likely this is a case of Non-Hodgkin Lymphoma with spillover in the peripheral blood . (Microscopy of Hodgkin’s lymphoma shows Reed Sternberg cells in a reactive background). NHLs can be identified on the basis of immunophenotyping:</p>\n<p><strong>Highyeild:</strong></p><p>CLL: CD 5+, CD 23+, CD 200+ Follicular Lymphoma: CD 10+, CD 5- Mantle cell Lymphoma: CD 5+, CD 10-, CD 23- Marginal Cell Lymphoma: CD 5-, CD 10- Hence, the next investigation that should be done is the Immunophenotyping of Peripheral Blood Lymphocytes . REMEMBER: Whenever there’s a question suggestive of Lymphoma, the next investigation would be a peripheral smear to differentiate NHL from HL and for any characteristic cells, if a peripheral smear is given, then the next investigation would be Immunophenotyping/ Immunohistochemistry to know the CD markers to narrow down the diagnosis, next investigation would be cytogenetics to know mutation and lastly bone marrow aspiration or biopsy for the staging of lymphoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. LN biopsy. False, LN biopsy will not help in narrowing the diagnosis. Option: C. Bone marrow aspiration. False, done after Cytogenetics to know to the stage. Option: D. Peripheral blood cytogenetics. False, done after immunophenotyping.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The marker for Lymphoma is:", "options": [{"label": "A", "text": "S-100", "correct": false}, {"label": "B", "text": "HMB-45", "correct": false}, {"label": "C", "text": "Leukocyte common antigen", "correct": true}, {"label": "D", "text": "Cytokeratin", "correct": false}], "correct_answer": "C. Leukocyte common antigen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leukocyte common antigen Since Lymphoma arises from mature leukocytes, Lymphoma cells are positive for Leukocyte common antigen (CD45) .</p>\n<p><strong>Highyeild:</strong></p><p>CD markers: Cells CD markers Immature CD34 Blast CD 34 Lymphoblast: TdT WBC CD 45 Myeloblast MPO, CD 13, 33, 117 Lymphoid ● B cells: CD19 , 20, 21, 22, 23, 24, CD 10, CD 79a, PAX 5 ● T cells: CD 3 , 1, 2, 4, 5, 6, 7, 8 ● NK cells: CD 16, 56 Monocytes CD 14, 64</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. S-100. Marker for peripheral nerve sheath tumours . S-100 protein is positive in all benign Schwann cell tumours . Option: B. HMB-45. Marker for melanoma . Option: D. Cytokeratin. Marker for Carcinoma .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The international prognostic index for lymphomas includes the following prognostic factors, except:", "options": [{"label": "A", "text": "Stage of disease", "correct": false}, {"label": "B", "text": "Number of extra lymphatic sites involved", "correct": false}, {"label": "C", "text": "LDH", "correct": false}, {"label": "D", "text": "Hemoglobin and albumin", "correct": true}], "correct_answer": "D. Hemoglobin and albumin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemoglobin and albumin International prognostic index for lymphomas do not include Hemoglobin and albumin</p>\n<p><strong>Highyeild:</strong></p><p>International Prognostic Index for NHL Five Clinical Risk Factors Age ≥60 years Serum lactate dehydrogenase levels elevated Performance status ≥2 (ECOG) or ≤70 (Karnofsky) Ann Arbor stage III or IV >1 site of extranodal involvement For Diffuse Large B-cell Lymphoma 0, 1 factor low risk 35% of cases; 5-year survival, 73% 2 factors low-intermediate risk 27% of cases; 5-year survival, 51% 3 factors high-intermediate risk 22% of cases; 5-year survival, 43% 4, 5 factors high risk 16% of cases; 5-year survival, 26% For Diffuse Large B-cell Lymphoma Treated With R-CHOP O factor = good 10% of cases; 4-year survival, 94% 1, 2 factors intermediate 45% of cases; 4-year survival, 80% 3, 4, 5 factors = poor 45% of cases; 4-year survival, 53% Abbreviations: ECOG, Eastern Cooperative Oncology Group; R-CHOP, rituximab, cyclophosphamide, doxorubicin, vincristine, prednisone.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Stage of disease. Correct . Option: B. Number of extra lymphatic sites involved. Correct . Option: C. LDH. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "About Burkitt’s lymphoma, true is-", "options": [{"label": "A", "text": "CD34 + ve & Surface Ig +ve", "correct": false}, {"label": "B", "text": "CD34 + ve & Surface Ig -ve", "correct": false}, {"label": "C", "text": "CD34 - ve & Surface Ig -ve", "correct": false}, {"label": "D", "text": "CD34 - ve & Surface Ig +ve", "correct": true}], "correct_answer": "D. CD34 - ve & Surface Ig +ve", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>CD34 - ve & Surface Ig +ve In Burkitt Lymphoma CD34 - ve & Surface Ig +ve CD34 is positive in Hematopoietic stem cells Classical triad of Burkitt’s lymphoma: CD19 +ve, Surface Ig +ve and CD34 - ve</p>\n<p><strong>Highyeild:</strong></p><p>Burkitt Lymphoma: Burkitt’s has a male predominance and is typically seen in patients <35 years of age . In Burkitt lymphoma , the tumour has a high mitotic index, and numerous apoptotic cells, combined with benign macrophages. Macrophages have abundant clear cytoplasm: a characteristic “ starry sky” pattern seen in Lymph Node biopsy. Mutation: C-MYC on Chromosome 8. t ( 8 ;14), t (2; 8 ), t ( 8 ;22). IHC: CD 10 +, CD19+, CD20+, and BCL6+, surface IgM+ Burkitt’s Lymphoma is the most common cause of tumour lysis syndrome . The classification of Burkitt’s Lymphoma Endemic (in Africa) 80-90% association with EBV. Most common site: Mandible . Sporadic 20-30% association with EBV. Most common site: The ileocaecal region . HIV associated 30-40% association with EBV. Most common site: Lymph node .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. p53 gene mutation. Germline mutation causes Li Fraumeni syndrome . Option: B. RB gene mutation. The mutation causes Retinoblastoma . Option: C. Translocation involving BCR-ABL genes. Seen with CML , a history of the 50-60-year-old patient would be given with leukocytosis, shift to left and basophilia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Burkitt’s lymphoma is -", "options": [{"label": "A", "text": "B cell lymphoma", "correct": true}, {"label": "B", "text": "6;14 translocations", "correct": false}, {"label": "C", "text": "Cannot present as an abdominal mass", "correct": false}, {"label": "D", "text": "Radiotherapy is used in the treatment", "correct": false}], "correct_answer": "A. B cell lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B cell lymphoma Burkitt’s lymphoma is a B-cell lymphoma , which can present as an abdominal mass</p>\n<p><strong>Highyeild:</strong></p><p>Burkitt Lymphoma: Burkitt’s has a male predominance and is typically seen in patients <35 years of age . In Burkitt lymphoma , the tumour has a high mitotic index, and numerous apoptotic cells, combined with benign macrophages. Macrophages have abundant clear cytoplasm: a characteristic “ starry sky” pattern seen in Lymph Node biopsy. Mutation: C-MYC on Chromosome 8. t ( 8 ;14), t (2; 8 ), t ( 8 ;22). IHC: CD 10 +, CD19+, CD20+, and BCL6+, surface IgM+ Burkitt’s Lymphoma is the most common cause of tumour lysis syndrome . Classification of Burkitt’s Lymphoma Endemic (in Africa) 80-90% association with EBV. Most common site: Mandible . Sporadic 20-30% association with EBV. Most common site: The ileocaecal region . HIV associated 30-40% association with EBV. Most common site: Lymph node .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. 6;14 translocations. False, C-MYC on Chromosome 8. t ( 8 ;14), t (2; 8 ), t ( 8 ;22) seen. Option: C. Cannot present as an abdominal mass. False . Option: D. Radiotherapy is used in treatment. False, Burkitt lymphoma is very aggressive but responds well to intensive chemotherapy .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The most malignant form of NHL is -", "options": [{"label": "A", "text": "Diffuse large B-cell lymphoma", "correct": true}, {"label": "B", "text": "Small cell lymphocytic lymphoma", "correct": false}, {"label": "C", "text": "Follicular cleavage", "correct": false}, {"label": "D", "text": "Large cell follicular lymphoma", "correct": false}], "correct_answer": "A. Diffuse large B-cell lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Diffuse large B-cell lymphoma Diffuse large B-cell lymphoma is the most aggressive lymphoma . Follicular lymphomas are low-grade and indolent.</p>\n<p><strong>Highyeild:</strong></p><p>Diffuse large B-cell lymphoma (DLBCL): A Most common type of Non-Hodgkin’s lymphoma ( NHLs ) in the world and India . Has the worst prognosis among NHLs . CD 19 +ve, CD 20 +ve, mostly surface IgM +ve and variable CD 6 and CD 10 positive. Cytogenetics: BCL6 translocation, t(14;18), MYC. Microscopy: The common features are a relatively large cell size (usually four to five times the diameter of a small lymphocyte) and a diffuse pattern of growth . More anaplastic tumours may contain multinucleated cells with large inclusion-like nucleoli that resemble Reed-Sternberg cells (the malignant cell of Hodgkin lymphoma). Clinical features: DLBCL typically presents as a rapidly enlarging mass at a nodal or extranodal site. It can arise virtually anywhere in the body. Waldeyer ring, the oropharyngeal lymphoid tissue that includes the tonsils and adenoids, is involved commonly. DLBCLs are aggressive tumours that are rapidly fatal without treatment . DLBCLs with MYC translocations have a worse prognosis than those without and may be better treated with chemotherapy regimens that are now standard for Burkitt lymphoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Small cell lymphocytic lymphoma. Incorrect . Option: C. Follicular cleavage. Incorrect . Option: D. Large cell follicular lymphoma. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 21 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following can change the gene expression by methylation and acetylation without changing the content of the gene-", "options": [{"label": "A", "text": "Translocation", "correct": false}, {"label": "B", "text": "Inversion", "correct": false}, {"label": "C", "text": "Mutation", "correct": false}, {"label": "D", "text": "Epigenetics", "correct": true}], "correct_answer": "D. Epigenetics", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Epigenetics</p>\n<p><strong>Highyeild:</strong></p><p>Epigenetics: Epigenetics is the study of heritable chemical modification of DNA or chromatin that does NOT alter the DNA sequence itself . Examples of such modification include the methylation of DNA and the methylation and acetylation of histones . Epigenetic modifications are critical for normal human development , including the regulation of tissue-specific gene expression , X chromosome inactivation , and imprinting , as well as for understanding the cellular perturbations in aging and cancer. Gene expression frequently correlates negatively with the level of methylation of DNA . Methylation analysis is also essential in diagnosing Prader-Willi syndrome and Angelman syndrome. MNEMONIC: M ethylation M utes DNA.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Translocation. In a translocation, a segment of one chromosome is transferred to another, e.g., BCR-ABL translocation 9;22 is seen in CML. Option: B. Inversion. It occurs when a segment breaks off and reattaches within the same chromosome but in reverse orientation. Option: C. Mutation. Permanent changes in DNA.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following disorders is due to maternal disomy of chromosome 15?", "options": [{"label": "A", "text": "Prader-Willi syndrome", "correct": true}, {"label": "B", "text": "Angelman syndrome", "correct": false}, {"label": "C", "text": "Turner syndrome", "correct": false}, {"label": "D", "text": "Klinefelter’s syndrome", "correct": false}], "correct_answer": "A. Prader-Willi syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Prader-Willi syndrome</p>\n<p><strong>Highyeild:</strong></p><p>Genomic imprinting: Preferential expression of genes from either parent. In Prader-Willi syndrome , deletion of band q12 on the long arm of paternal chromosome 15 Genes in this region of maternal chromosome 15 are imprinted, so their functions are completely lost. Patients have mental retardation, short stature, hypotonia, hyperphagia, small hands and feet, and hypogonadism . In Angelman syndrome, the same region is deleted from the maternal chromosome . Since genes on the corresponding region of paternal chromosome 15 are imprinted, these patients have mental retardation, ataxia, seizures, and inappropriate laughter . REMEMBER: Prader-Willi syndrome is because of the following: Deletion of Paternal chromosomes . Disomy of Paternal chromosomes . Angelman syndrome is because of the following: Deletion of Maternal chromosomes . Disomy of Paternal chromosomes .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Angelman syndrome. Disomy of Paternal chromosomes Option: C. Turner syndrome. A chromosomal disorder in which a female is born with only one X chromosome (XO). Option: D. Klinefelter’s syndrome. A genetic condition in which a male is born with an extra copy of the X chromosome (XXY).</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Karyotyping is done with all except:", "options": [{"label": "A", "text": "Blood lymphocyte", "correct": false}, {"label": "B", "text": "Blood monocyte", "correct": true}, {"label": "C", "text": "Amnion", "correct": false}, {"label": "D", "text": "Fibroblast", "correct": false}], "correct_answer": "B. Blood monocyte", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Blood monocyte The study of chromosomes is called karyotyping. Karyotype from a normal male is shown below: Human somatic cells contain 46 chromosomes; these comprise 22 homologous pairs of autosomes and two sex chromosomes, XX in the female and XY in the male. The usual procedure to examine chromosomes is to arrest dividing cells in metaphase with mitotic spindle inhibitors (e.g., N-diacetyl-N-methylcolchicine [Colcemid]) and then to stain the chromosomes. In a metaphase spread, the individual chromosomes form two chromatids connected at the centromere. A karyotype is obtained by arranging each pair of autosomes according to length, followed by sex chromosomes . Various staining methods have been developed to identify individual chromosomes based on a distinctive and reliable pattern of alternating light and dark bands. The one most commonly used involves a Giemsa stain and is hence called G banding . Standard G banding can detect approximately 400 to 800 bands per haploid set. It is done with blood lymphocytes , amnion and fibroblast .</p>\n<p><strong>Highyeild:</strong></p><p>Genomic imprinting: Preferential expression of genes from either parent. In Prader-Willi syndrome , deletion of band q12 on the long arm of paternal chromosome 15 Genes in this region of maternal chromosome 15 are imprinted, so their functions are completely lost. Patients have mental retardation, short stature, hypotonia, hyperphagia, small hands and feet, and hypogonadism . In Angelman syndrome, the same region is deleted from the maternal chromosome . Since genes on the corresponding region of paternal chromosome 15 are imprinted, these patients have mental retardation, ataxia, seizures, and inappropriate laughter . REMEMBER: Prader-Willi syndrome is because of the following: Deletion of Paternal chromosomes . Disomy of Paternal chromosomes . Angelman syndrome is because of the following: Deletion of Maternal chromosomes . Disomy of Paternal chromosomes .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Blood lymphocyte. Correct . Option: C. Amnion. Correct . Option: D. Fibroblast. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mitochondrial DNA (mt-DNA) is known for all except:", "options": [{"label": "A", "text": "Maternal inheritance", "correct": false}, {"label": "B", "text": "Heteroplasmy", "correct": false}, {"label": "C", "text": "Leber's hereditary optic neuropathy is the prototype", "correct": false}, {"label": "D", "text": "Duchene’s muscular dystrophy results due to mutations in mt-DNA", "correct": true}], "correct_answer": "D. Duchene’s muscular dystrophy results due to mutations in mt-DNA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Duchene’s muscular dystrophy results due to mutations in mt-DNA</p>\n<p><strong>Highyeild:</strong></p><p>Mitochondrial DNA: Maternal inheritance is a feature unique to mtDNA , as, during zygote formation, mutated mitochondrial DNA comes from Ova . Each mitochondrion contains thousands of copies of mtDNA, and typically, deleterious mtDNA mutations affect some but not all of these copies. Thus, tissues and individuals may harbour both wild-type and mutant mtDNA, a heteroplasmy situation. Mitochondria and their contained DNA are randomly distributed to the daughter cells during cell division. Thus, when a cell containing normal and mutant mtDNA divides, the proportion of the normal and mutant mtDNA in daughter cells is extremely variable. Therefore, the expression of disorders resulting from mutations in mtDNA is quite variable . Diseases associated with mitochondrial inheritance are rare, and many of them affect the neuromuscular system. Leber hereditary optic neuropathy is a prototype of this type of disorder. It is a neurodegenerative disease that manifests as a progressive bilateral loss of central vision . Duchene’s muscular dystrophy is X-linked (XR) .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Maternal inheritance. Correct . Option: B. Heteroplasmy. Correct . Option: C. Leber hereditary optic neuropathy is the prototype. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Examples of diseases that are mitochondrial in inheritance: Kearn Sayne Syndrome Leigh Syndrome MELAS MERRF NARP Lebers Hereditary Optic Neuropathy Pearson Syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 20-year-old female physician to the physician with complaints of progressive bilateral loss of Central vision for the last three years. She also has cardiac conduction defects and minor neurological manifestations. The treating doctor thought it was a genetic disease and asked for relevant history and formed the following Pedigree chart. What is most likely the diagnosis?", "options": [{"label": "A", "text": "Diabetic neuropathy", "correct": false}, {"label": "B", "text": "Leber optic neuropathy", "correct": true}, {"label": "C", "text": "Fragile X syndrome", "correct": false}, {"label": "D", "text": "Down syndrome", "correct": false}], "correct_answer": "B. Leber optic neuropathy", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822349269-QTDP034007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leber optic neuropathy Pedigree of Leber hereditary optic neuropathy is shown It is a disorder caused by a mutation in mitochondrial DNA . Note that all progeny of an affected male (shaded squares) are normal , but all children, male and female, of the affected female (shaded circles) manifest disease to a variable degree . Most genes are located on chromosomes in the cell nucleus and are inherited in a classic Mendelian fashion. Several mitochondrial genes exist, however, that are inherited in quite a different manner. A feature unique to mtDNA is maternal inheritance . This peculiarity exists because ova contain numerous mitochondria within their abundant cytoplasm, whereas spermatozoa contain few, if any . Hence the mtDNA complement of the zygote is derived entirely from the ovum.</p>\n<p><strong>Highyeild:</strong></p><p>Mitochondrial DNA: Maternal inheritance is a feature unique to mtDNA , as, during zygote formation, mutated mitochondrial DNA comes from Ova . Each mitochondrion contains thousands of copies of mtDNA, and typically, deleterious mtDNA mutations affect some but not all of these copies. Thus, tissues and individuals may harbour both wild-type and mutant mtDNA, a heteroplasmy situation. Mitochondria and their contained DNA are randomly distributed to the daughter cells during cell division. Thus, when a cell containing normal and mutant mtDNA divides, the proportion of the normal and mutant mtDNA in daughter cells is extremely variable. Therefore, the expression of disorders resulting from mutations in mtDNA is quite variable . Diseases associated with mitochondrial inheritance are rare, and many of them affect the neuromuscular system. Leber hereditary optic neuropathy is a prototype of this type of disorder. It is a neurodegenerative disease that manifests as a progressive bilateral loss of central vision .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Diabetic neuropathy. Diabetes mellitus has a complex genetic spread . It is not a mitochondrial DNA-related disease. Option: C. Fragile X syndrome. Occurs due to pathological amplification of trinucleotide repeat causes loss of function or gain-of-function mutations such mutation produce neurodegenerative disorders. Fragile X syndrome results from the loss of FMR1 gene function and is characterised by mental retardation, macroorchidism and abnormal facial features . Option: D. Down syndrome. Down syndrome is due to trisomy 21, which is not associated with maternal mitochondrial inheritance.</p>\n<p><strong>Extraedge:</strong></p><p>Examples of diseases that are mitochondrial in inheritance: Kearn Sayne Syndrome Leigh Syndrome MELAS MERRF NARP Lebers Hereditary Optic Neuropathy Pearson Syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 46-year-old man is brought to the physician by his wife because of a 6-month history of progressive memory loss and personality changes. His wife says that his father developed similar symptoms at 50, and his grandfather developed the same symptoms at age 55. Physical examination shows involuntary twitching movements of the limbs and poor coordination. Which of the following genetic mechanisms is most likely involved in this disorder?", "options": [{"label": "A", "text": "Expanded trinucleotide tandem repeat", "correct": true}, {"label": "B", "text": "Genomic imprinting", "correct": false}, {"label": "C", "text": "Large deletion in one gene", "correct": false}, {"label": "D", "text": "Translocation", "correct": false}], "correct_answer": "A. Expanded trinucleotide tandem repeat", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Expanded trinucleotide tandem repeat Huntington's Disease is an autosomal dominant (AD) disease caused by the degeneration of striatal neurons and characterised by a progressive movement disorder and dementia.</p>\n<p><strong>Highyeild:</strong></p><p>Trinucleotide repeat disorders Several disorders, including Huntington's disease , are caused by expanding a three-base sequence within a specific gene. The majority of trinucleotide expansion disorders share certain common features. Some individuals display premutation , a characteristic in which the copy number of the trinucleotide is increased and unstable, but their phenotype is normal . Individuals with premutations may pass on further expanded trinucleotide tracts to their offspring, evident in the patient's ages, father, and grandfather when they developed the clinical symptoms. In Huntington's disease, there are CAG repeats which in normal individuals is 6 to 35 copies of the repeat; when the number of repetitions is increased beyond this level, it is associated with the disease. There is an inverse relationship between repeat number and age of onset , such that longer repeats tend to be associated with an earlier start in the next generation , a phenomenon termed Anticipation (as evidenced by the history provided).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Genomic imprinting. E.g., Prader-Willi and Angelman syndromes Option: C. Large deletion in one gene. Duchenne muscular dystrophy is an X-linked Recessive disease due to a large deletion in the gene that encodes dystrophin . Option: D. Translocations of chromosomes give rise to several disorders, including chronic myelogenous leukaemia ( CML ; Philadelphia chromosome ), in which a translocation occurs between chromosomes 9 and 22, t (9;22) , producing the oncogenic fusion protein BCR-ABL .</p>\n<p><strong>Table:</strong></p><p>Examples of\n Trinucleotide-Repeat Disorders Disease Gene Locus Protein Repeat Expansions Affecting Noncoding\n Regions Fragile X syndrome FMRI (FRAXA) Xq27.3 FMR-1 protein (FMRP) CGG Friedreich ataxia XFXN 9q21.1 Frataxin GAA Myotonic dystrophy DMPK 1913.3 Myotonic dystrophy protein kinase (DMPK) CTG Expansions Affecting Coding\n Regions Spinobulbar muscular atrophy\n (Kennedy disease) AR Xq12 Androgen receptor (AR) CAG Huntington disease HTT 4p16.3 Huntingtin CAG Dentatorubral-pallidoluysian\n atrophy (Haw River syndrome) ATNL 12p13.31 Atrophin-1 CAG Spinocerebellar ataxia type I ATXNI 6р23 Ataxin-1 CAG Spinocerebellar ataxia type 2 ATXN2 12q24.1 Ataxin-2 CAG Spinocerebellar ataxia type 3\n (Machado-Joseph disease) ATXN3 14q21 Ataxin-3 CAG Spinocerebellar ataxia type 6 Ataxin-6 19p13.3 α 1A -Voltage-dependent calcium\n channel subunit CAG Spinocerebellar ataxia type 7 Atoxin-7 3p14.1 Ataxin-7 CAG</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 45-year-old male, Arvind, previously diagnosed with depression, is now experiencing involuntary grimacing and strange movements of his arms and legs. Neurological examination shows normal strength and normal deep tendon reflexes. No sensory deficits are noted. The patient's grandfather died of a neurological disease at 65, and the patient's father died of a similar disease at 58. This patient has an earlier onset of disease than either his father or grandfather and is most likely explained by which of the following?", "options": [{"label": "A", "text": "Increased penetrance", "correct": false}, {"label": "B", "text": "Pleiotropy", "correct": false}, {"label": "C", "text": "Anticipation", "correct": true}, {"label": "D", "text": "Mosaicism", "correct": false}], "correct_answer": "C. Anticipation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anticipation</p>\n<p><strong>Highyeild:</strong></p><p>Huntington's Disease is an autosomal dominant disease caused by the degeneration of striatal neurons and characterised by a progressive movement disorder and dementia . Jerky, hyperkinetic, sometimes dystonic movements involving all parts of the body (chorea) are characteristic; affected individuals may later develop bradykinesia and rigidity. It is a prototypic polyglutamine trinucleotide repeat expansion disease with CAG repeats that encode a polyglutamine region. Normal genes contain 6 to 35 copies of the repeat; when the number of repetitions is increased beyond this level , it is associated with the disease . There is an inverse relationship between repeat number and age of onset, such that longer repeats tend to be associated with earlier onset . The brain is small and shows striking atrophy of the caudate nucleus and the putamen , components of the dorsal striatum; the globus pallidus may atrophy secondarily, and the lateral and third ventricles are dilated.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Increased penetrance. The transmission of an abnormal gene from parent to child does not always cause disease; the likelihood that the properties of a gene will be expressed is called penetrance . Huntington's disease is a disorder with 100% penetrance means all individuals who have an abnormal HD gene will develop Huntington's disease . Option: B. Pleiotropy. Sometimes one gene mutation leads to multiple phenotypic abnormalities. This genetic phenomenon is called pleiotropy . In Huntington's disease, pleiotropy is present because the mutation of one gene causes dysfunction of behaviour movement and cognition altogether . Option: D. Mosaicism. The presence of two populations of cells with different genotypes in one patient is known as mosaicism . Examples include milder forms of Turner, Klinefelter and Down syndrome.</p>\n<p><strong>Extraedge:</strong></p><p>Anticipation : This refers to the observation that clinical features of Huntington Disease worsen with each successive generation as if the mutation becomes increasingly deleterious as it is transmitted from a man to his sons and grandsons. Anticipation is seen with trinucleotide repeat disorders, as in Fragile X syndrome, Myotonic Dystrophy and Friedrich Ataxia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A young boy, Rinku, is being evaluated for developmental delay, mild autism, and intellectual disability. Physical examination reveals the boy to have large, everted ears and a long face with a large mandible. He is also found to have Macroorchidism (large testes), and extensive workup reveals multiple tandem repeats of the nucleotide sequence CGG in his DNA. Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Fragile X syndrome", "correct": true}, {"label": "B", "text": "Huntington's chorea", "correct": false}, {"label": "C", "text": "Myotonic dystrophy", "correct": false}, {"label": "D", "text": "Ataxia-telangiectasia", "correct": false}], "correct_answer": "A. Fragile X syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fragile X syndrome</p>\n<p><strong>Highyeild:</strong></p><p>Fragile X syndrome Most common genetic cause of intellectual disability Overall 2nd most common cause of intellectual disability after Downs (REMEMBER that Downs is not a genetic cause of intellectual disability) Trinucleotide repeats CGG in FMR-1 gene seen Clinical features: Large ears Large mandible Intellectual disability Macroorchidism</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Huntington's chorea. CAG repeats are seen, and symptoms include movement disorders and dementia . Option: C. Myotonic dystrophy. CTG repeats are seen, and symptoms include gradually worsening muscle loss and weakness. Muscles often contract and are unable to relax . Other symptoms may include Christmas tree cataracts , intellectual disability and heart conduction problems . Option: D. Ataxia-telangiectasia. The autosomal recessive disorder is primarily characterised by cerebellar degeneration, telangiectasia, immunodeficiency, cancer susceptibility and radiation sensitivity .</p>\n<p><strong>Table:</strong></p><p>Trinucleotide repeats: · In Coding region: o Huntington's disease (CAG) · In the Non-coding region: o Fragile X syndrome (CGG) o Fredrichs Ataxia (GAA) o Myotonia Dystrophica (CTG)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is false about the given pedigree chart?", "options": [{"label": "A", "text": "Leber hereditary optic neuropathy is an example", "correct": false}, {"label": "B", "text": "Father never transmits to the child", "correct": false}, {"label": "C", "text": "Type of classical Mendelian inheritance", "correct": true}, {"label": "D", "text": "All children of mothers are affected", "correct": false}], "correct_answer": "C. Type of classical Mendelian inheritance", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822410759-QTDP035003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Type of classical Mendelian inheritance This pedigree is an example of maternal or mitochondrial inheritance .</p>\n<p><strong>Highyeild:</strong></p><p>Mitochondrial DNA: A feature unique to mtDNA is maternal inheritance, as, during zygote formation, mutated mitochondrial DNA comes from Ova . Each mitochondrion contains thousands of copies of mtDNA, and typically, deleterious mtDNA mutations affect some but not all of these copies. Thus, tissues and individuals may harbour both wild-type and mutant mtDNA, a heteroplasmy situation. Mitochondria and their contained DNA are randomly distributed to the daughter cells during cell division. Thus, when a cell containing normal and mutant mtDNA divides, the proportion of the normal and mutant mtDNA in daughter cells is highly variable. Therefore, the expression of disorders resulting from mutations in mtDNA is quite variable . Diseases associated with mitochondrial inheritance are rare, and many of them affect the neuromuscular system. Leber hereditary optic neuropathy is a prototype of this type of disorder. It is a neurodegenerative disease that manifests as a progressive bilateral loss of central vision .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Leber hereditary optic neuropathy is an example. Leber's hereditary optic neuropathy is a mitochondrial inherited degeneration of retinal ganglion cells and their axons, leading to an acute or subacute loss of central vision . Option: B. Father never transmits to the child. True statement . Option: D. All children of mothers are affected. True statement .</p>\n<p><strong>Extraedge:</strong></p><p>Mitochondrial inheritance: Kearn Sayne Syndrome Leigh Syndrome MELAS MERRF NARP Lebers Hereditary Optic Neuropathy Pearson Syndrome</p>\n<p><strong>Table:</strong></p><p>Modes of inheritance: Autosomal Dominant: System Disorder Nervous Huntington disease Neurofibromatosis Myotonic dystrophy Tuberous sclerosis Urinary Polycystic kidney disease Gastrointestinal Familial polyposis coli Hematopoietic Hereditary spherocytosis von Willebrand disease Skeletal Marfan syndromeª Ehlers-Danlos syndrome (some variants)a Osteogenesis imperfecta Achondroplasia Metabolic Familial hypercholesterolemiaª Acute intermittent\n porphyria</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about the given image, except:", "options": [{"label": "A", "text": "It is the most common chromosomal cause of mental retardation", "correct": false}, {"label": "B", "text": "Incidence increases with increased maternal age", "correct": false}, {"label": "C", "text": "90 per cent of the child born with congenital cardiac anomalies", "correct": true}, {"label": "D", "text": "Not all children suffering from this syndrome have trisomy 21", "correct": false}], "correct_answer": "C. 90 per cent of the child born with congenital cardiac anomalies", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686822410778-QTDP035004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>90 per cent of the child born with congenital cardiac anomalies Approximately 40% of the patients have congenital heart disease , most commonly endocardial cushion defects, including ostium primum, atrial septal defects, atrioventricular valve malformations, and ventricular septal defects.</p>\n<p><strong>Highyeild:</strong></p><p>Trisomy 21 (Down Syndrome) Down syndrome is the most common of the chromosomal disorders and is a significant cause of intellectual disability . FISH with chromosome 21–specific probes reveal the extra copy of chromosome 21 in such cases. The most common cause of trisomy and, therefore, of Down syndrome is meiotic nondisjunction . Maternal age has a strong influence on the incidence of trisomy 21 . The classical presentation includes: Flat facial profile Epicanthic folds Oblique palpebral fissures Simian crease Sandal gap Predisposition to leukaemia Intellectual disability</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is the most common chromosomal cause of mental retardation. Down syndrome is the most common of the chromosomal disorders and is a significant cause of mental retardation . Option: B. Incidence increases with increased maternal age. Maternal age has a strong influence on the incidence of trisomy 21 . It occurs once in 1550 live births for women under age 20, in contrast to 1 in 25 live births for mothers older than 45. The correlation with maternal age suggested that, in most cases, the meiotic nondisjunction of chromosome 21 occurs in the ovum. Option: D. Not all children suffering from this syndrome have trisomy 21. Approximately 95% of affected individuals have trisomy 21, so their chromosome count is 47 . FISH with chromosome 21–specific probes reveal the extra copy of chromosome 21 in such cases. Most others have normal chromosome numbers, but the additional chromosomal material is present as a translocation .</p>\n<p><strong>Extraedge:</strong></p><p>Down syndrome's most frequent forms of congenital heart disease are atrioventricular septal defects . Cardiac problems are responsible for most infant and early childhood deaths. Several other congenital malformations, including atresias of the esophagus and small bowel , are also common. Children with trisomy 21 have a high risk of developing Leukemia ; there is a 20-fold increased risk of developing acute B lymphoblastic leukaemias and a 500-fold increased risk of acute myeloid leukemias . The latter, most commonly, is acute megakaryoblastic leukemia (M7) . Almost all patients with trisomy 21 older than age 4 0 develop neuropathologic changes characteristic of Alzheimer's , a degenerative brain disorder. ( PYQ ) Patients with Down syndrome have abnormal immune responses predisposing them to severe infections, particularly of the lungs, and thyroid autoimmunity .</p>\n<p><strong>Table:</strong></p><p>Down Syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 6-year-old child is brought to the pediatrician by his parents. He has bony deformities and a blue sclera. On investigation, it was found he has sensorineural deafness also. Both his parents are normal. What kind of inheritance is seen in this syndrome?", "options": [{"label": "A", "text": "Autosomal dominant", "correct": false}, {"label": "B", "text": "Autosomal recessive", "correct": false}, {"label": "C", "text": "Germline mosaicism", "correct": true}, {"label": "D", "text": "Both AC", "correct": false}], "correct_answer": "C. Germline mosaicism", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Germline mosaicism From the data given, a diagnosis of osteogenesis imperfecta is made. Inheritance of osteogenesis imperfecta can be Autosomal dominant or a new mutation (Germline mosaicism) . Both parents are normal in the given question; hence, autosomal dominance can't be an answer . So Germline mosaicism is the answer.</p>\n<p><strong>Highyeild:</strong></p><p>Osteogenesis imperfecta Genetic bone disorder (brittle bone disease) is caused by various gene defects (most commonly COL1A1 and COL1A2 ). The most common form is autosomal dominant, with decreased production of otherwise normal type I collagen (altered triple helix formation). The fundamental abnormality in Osteogenesis Imperfecta is too little bone, resulting in extreme skeletal fragility. Clinical manifestations include: Multiple fractures and bone deformities after minimal trauma (e.g., during birth). Blue sclerae due to the translucent connective tissue over choroidal veins. Some forms have tooth abnormalities , including opalescent teeth that wear easily due to a lack of dentin (dentinogenesis imperfecta). Conductive hearing loss (abnormal ossicles). Treatment : Bisphosphonates to decrease fracture risk.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Autosomal dominant. Incorrect . Option: B. Autosomal recessive. Incorrect . Option: D. Both A&C. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true statements, except:", "options": [{"label": "A", "text": "Fragile X syndrome - trinucleotide repeat CGG", "correct": false}, {"label": "B", "text": "Friedreich Ataxia- trinucleotide repeat GAA", "correct": false}, {"label": "C", "text": "Huntington disease- trinucleotide repeat CAG", "correct": false}, {"label": "D", "text": "Myotonic dystrophy- trinucleotide repeat CGT", "correct": true}], "correct_answer": "D. Myotonic dystrophy- trinucleotide repeat CGT", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myotonic dystrophy- trinucleotide repeat CGT</p>\n<p><strong>Highyeild:</strong></p><p>Trinucleotide repeats It is trinucleotide repeat CTG which is seen in Myotonic dystrophy . Myotonic dystrophy is characterised by progressive muscle wasting and weakness . People with this disorder often have prolonged muscle contractions (myotonia) and cannot relax certain muscles after use.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fragile X syndrome - trinucleotide repeat CGG. Fragile X syndrome is the prototype of a disease in which the mutation is characterised by a long repeating sequence of three nucleotides CGG . Other symptoms may include Christmas tree cataracts , intellectual disability and heart conduction problems . Option: B. Friedreich Ataxia- trinucleotide repeat GAA. Friedreich's ataxia is a rare genetic disease that causes difficulty walking, a loss of sensation in the arms and legs, and impaired speech. It's also known as spinocerebellar degeneration . Trinucleotide repeat GAA is seen. Option: C. Huntington disease- trinucleotide repeat CAG. Huntington's disease is due to trinucleotide repeat CAG . Symptoms include movement disorders and dementia .</p>\n<p><strong>Table:</strong></p><p>Trinucleotide repeats: · In Coding region: o Huntington's disease (CAG) · In the Non-coding region: o Fragile X syndrome (CGG) o Fredrichs Ataxia (GAA) o Myotonia Dystrophica (CTG)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A child has a long face, large mandible, large everted ears, large testicles, high arched palate, and IQ of 30. All are true about this syndrome, except:", "options": [{"label": "A", "text": "Trinucleotide repeat of CGG is responsible", "correct": false}, {"label": "B", "text": "Risk of disease decreases with successive generations", "correct": true}, {"label": "C", "text": "It is caused by a trinucleotide mutation in the familial mental retardation-1 (FMR1) gene", "correct": false}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "B. Risk of disease decreases with successive generations", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Risk of disease decreases with successive generations</p>\n<p><strong>Highyeild:</strong></p><p>Fragile X syndrome Most common genetic cause of intellectual disability Overall 2nd most common cause of intellectual disability after Downs (REMEMBER that Downs is not a genetic cause of intellectual disability) Trinucleotide repeats CGG in FMR-1 gene seen Clinical features: Large ears Large mandible Intellectual disability Macroorchidism Clinical features of Fragile X syndrome worsen with each successive generation as if the mutation becomes increasingly deleterious as transmitted from a man to his grandsons and great-grandsons (through daughters).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Trinucleotide repeat of CGG is responsible. True . Option: C. Is caused by a trinucleotide mutation in the familial mental retardation-1 (FMR1) gene. True . Option: D. All the above statements are true. Incorrect statement .</p>\n<p><strong>Table:</strong></p><p>Trinucleotide\nrepeats: · In\nCoding region: o Huntington's disease (CAG) · In the Non-coding region: o Fragile X syndrome (CGG) o Fredrichs Ataxia (GAA) o Myotonia Dystrophica (CTG)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 17 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding Fatty streaks except:", "options": [{"label": "A", "text": "Begin as multiple small yellow spots", "correct": false}, {"label": "B", "text": "It may coalesce into an elongated yellow Streak measuring up to 1 cm", "correct": false}, {"label": "C", "text": "It may impinge on the lumen and causes haemodynamic disturbances", "correct": true}, {"label": "D", "text": "Aorta of infants can show a Fatty streak", "correct": false}], "correct_answer": "C. It may impinge on the lumen and causes haemodynamic disturbances", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It may impinge on the lumen and causes haemodynamic disturbances</p>\n<p><strong>Highyeild:</strong></p><p>Fatty streaks are composed of lipid-filled foamy macrophages . Beginning as multiple-minute flat yellow spots , they eventually coalesce into elongated streaks 1 cm long or longer. These lesions are not sufficiently raised to cause any significant flow disturbances . Although fatty streaks can evolve into plaques , not all are destined to become advanced lesions. The aortas of infants can exhibit fatty streaks , and such lesions are present in virtually all adolescents , even those without known risk factors.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Begin as multiple small yellow spots. True . Option: B. It may coalesce into an elongated yellow Streak measuring up to 1 cm. True . Option: D. Aorta of infants can show a Fatty streak. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding atherosclerotic plaques except:", "options": [{"label": "A", "text": "It is yellow-white and encroaches on the lumen of the artery", "correct": false}, {"label": "B", "text": "It is patchy and usually involves a portion of the blood vessel", "correct": false}, {"label": "C", "text": "It is usually circumferential", "correct": true}, {"label": "D", "text": "Branch points of the vessels are susceptible to atherosclerosis plaques", "correct": false}], "correct_answer": "C. It is usually circumferential", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is usually circumferential The key processes in atherosclerosis are intimal thickening and lipid accumulation , which together form plaques . Atheromatous plaques are white-yellow and encroach on the lumen of the artery ; the superimposed thrombus over ulcerated plaques is red-brown . Plaques vary in size but can coalesce to form larger masses. Atherosclerotic lesions are patchy , usually involving only a portion of any given arterial wall and are rarely circumferential ; on cross-section, the lesions, therefore, appear eccentric . Local flow disturbances, such as turbulence at branch points, make certain portions of a vessel wall more susceptible to plaque formation Atherosclerotic plaques are susceptible to clinically important pathologic changes. The thickness and ECM content of the overlying fibrous cap will impact the stability or fragility of the plaque and its tendency to undergo secondary changes. Rupture, ulceration, or erosion of the surface of atheromatous plaques exposes the bloodstream to highly thrombogenic substances and leads to thrombosis , which can partially or completely occlude the vessel lumen . If the patient survives, the thrombus may organize and become incorporated into the growing plaque. Haemorrhage into a plaque . Rupture of the overlying fibrous cap or the thin-walled vessels in the areas of neovascularization can cause intraplaque haemorrhage; a contained hematoma may expand the plaque or induce plaque rupture . Atheroembolism . Plaque rupture can discharge atherosclerotic debris into the bloodstream, producing microemboli . Aneurysm formation . Atherosclerosis-induced pressure or ischemic atrophy of the underlying media, with loss of elastic tissue, causes weakness and potential rupture.</p>\n<p><strong>Highyeild:</strong></p><p>Pathogenesis of Atherosclerosis: Endothelial injury and dysfunction, cause (among other things) increased vascular permeability, leukocyte adhesion, and thrombosis . Accumulation of lipoproteins (mainly LDL and its oxidized forms) in the vessel wall. Monocyte adhesion to the endothelium, followed by migration into the intima and transformation into macrophages and foam cells . Platelet adhesion . Factor release from activated platelets, macrophages, and vascular wall cells, inducing smooth muscle cell recruitment , either from the media or from circulating precursors. Smooth muscle cell proliferation , ECM production , and recruitment of T cells. Lipid accumulation both extracellularly and within cells (macrophages and smooth muscle cells). Calcification of ECM and necrotic debris late in the pathogenesis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is yellow-white and encroaches on the lumen of the artery. True . Option: B. It is patchy and usually involves a portion of the blood vessel. True . Option: D. Branch points of the vessels are susceptible to atherosclerosis plaques. True .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the histology of atherosclerotic plaque except :", "options": [{"label": "A", "text": "Superficial fibrous cap composed of smooth muscle and collagen", "correct": false}, {"label": "B", "text": "Shoulder of the cap has more cellular area containing macrophages, T cells, and smooth muscle cells", "correct": false}, {"label": "C", "text": "Deep to the cap there is the necrotic zone containing lipids, debris from dead cells, foam cells", "correct": false}, {"label": "D", "text": "Neovascularization seen in the central area of the plaque", "correct": true}], "correct_answer": "D. Neovascularization seen in the central area of the plaque", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neovascularization seen in the central area of the plaque</p>\n<p><strong>Highyeild:</strong></p><p>Typically, there is a superficial fibrous cap composed of smooth muscle cells and relatively dense collagen . Beneath and to the side of the cap (the “ shoulder ”) is a more cellular area containing macrophages, T cells, and smooth muscle cells. Deep to the fibrous cap is a necrotic core , containing lipid (primarily cholesterol and cholesterol esters), debris from dead cells, foam cells (lipidladen macrophages and smooth muscle cells), fibrin, variably organized thrombus, and other plasma proteins; the cholesterol content is frequently present as crystalline aggregates that are washed out during routine tissue processing and leave behind only empty “clefts.” The periphery of the lesions demonstrates neovascularization (proliferating small blood vessels).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Superficial fibrous cap composed of smooth muscle and collagen. True . Option: B. The shoulder of the cap has more cellular area containing macrophages, T cells, and smooth muscle cells. True . Option: C. Deep to the cap there is the necrotic zone containing lipids, debris from dead cells, and foam cells. True .</p>\n<p><strong>Extraedge:</strong></p><p>Arteriosclerosis literally means “ hardening of the arteries ”; it is a generic term for arterial wall thickening and loss of elasticity. There are four general patterns , with different clinical and pathologic consequences. Arteriolosclerosis affects small arteries and arterioles and may cause downstream ischemic injury. There are two anatomic variants, hyaline and hyperplastic . Mönckeberg medial sclerosis is characterized by calcifications of the medial walls of muscular arteries, typically starting along the internal elastic membrane. Adults older than age 50 are most commonly affected. The calcifications do NOT encroach on the vessel lumen and are usually not clinically significant . Fibromuscular intimal hyperplasia occurs in muscular arteries larger than arterioles. It is driven by inflammation (as in a healed arteritis or transplant-associated arteriopathy) or by mechanical injury (e.g., associated with stents or balloon angioplasty; see later) and can be considered as a healing response. The affected vessels can become quite stenotic; indeed, such intimal hyperplasia underlies in-stent restenosis and is the major long-term limitation of solid-organ transplants. Atherosclerosis , from Greek root words for “gruel” and “hardening,” is the most frequent and clinically important pattern and is discussed here.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following gene mutations is responsible for the majority of cases of hereditary pancreatitis?", "options": [{"label": "A", "text": "PRSS 1", "correct": true}, {"label": "B", "text": "SPINK 1", "correct": false}, {"label": "C", "text": "CASR", "correct": false}, {"label": "D", "text": "CFTR", "correct": false}], "correct_answer": "A. PRSS 1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PRSS 1 Hereditary pancreatitis is a rare genetic disorder characterized by recurrent episodes of acute pancreatitis that can progress to chronic pancreatitis. The majority of cases of hereditary pancreatitis are caused by mutations in the PRSS1 gene , which provides instructions for making an enzyme called cationic trypsinogen. Mutations in the PRSS1 gene can cause the enzyme to become overactive , leading to inflammation and damage to pancreatic tissue.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. SPINK 1:Mutations in the SPINK1 gene can impair the function of the protein pancreatic secretory trypsin inhibitor, leading to increased trypsin activity and pancreatic damage. But it is less common than PRSS1 Option: C. CASR: Mutations in the CASR gene have been associated with an increased risk of developing pancreatitis, but their exact role in the development of hereditary pancreatitis is not well understood. Option:D. CFTR: Mutations in the CFTR gene can disrupt the normal functioning of the pancreas and lead to the development of pancreatitis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are risk factors for the development of acute pancreatitis except:", "options": [{"label": "A", "text": "Alcoholism", "correct": false}, {"label": "B", "text": "Hypercalcemia", "correct": false}, {"label": "C", "text": "Hypertriglyceridemia", "correct": false}, {"label": "D", "text": "Islet cell hypertrophy", "correct": true}], "correct_answer": "D. Islet cell hypertrophy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Islet cell hypertrophy Acute pancreatitis is a condition characterized by inflammation of the pancreas, which can be caused by various factors. However, islet cell hypertrophy, which refers to an enlargement of the pancreatic islet cells responsible for producing insulin, is not considered a risk factor for acute pancreatitis.</p>\n<p><strong>Highyeild:</strong></p><p>Causes of acute pancreatitis Mnemonic: I GET SMASHED I- Idiopathic G - Gallstones E - Ethanol T - Trauma S - Steroids M - Mumps virus A - Autoimmune S - Scorpion sting H - Hyperlipidemia or hypercalcemia E - ERCP (endoscopic retrograde cholangiopancreatography) D - Drugs (such as azathioprine, diuretics, and valproic acid)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Alcoholism: Heavy alcohol consumption is one of the most common causes of acute pancreatitis. Option: B. Hypercalcemia: High levels of calcium in the blood can cause damage to the pancreatic cells and lead to the development of pancreatitis. Option: C. Hypertriglyceridemia: High levels of triglycerides in the blood can also cause damage to the pancreatic cells and lead to the development of pancreatitis.</p>\n<p><strong>Extraedge:</strong></p><p>Revised Atlanta Criteria for Diagnosis of Acute Pancreatitis: It requires the presence of at least two of the following three criteria: Abdominal pain : The patient must have severe, persistent, epigastric or upper abdominal pain that may radiate to the back or chest. Elevated serum lipase or amylase levels : The patient must have a serum lipase or amylase level greater than three times the upper limit of normal. Imaging findings suggestive of acute pancreatitis : The patient must have imaging findings that are consistent with acute pancreatitis, such as pancreatic edema, inflammation, or necrosis, as seen on ultrasound, CT scan, or MRI.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of acute pancreatitis in the pancreas except:", "options": [{"label": "A", "text": "Inflammation", "correct": false}, {"label": "B", "text": "Edema", "correct": false}, {"label": "C", "text": "Fat necrosis", "correct": false}, {"label": "D", "text": "Fibrosis", "correct": true}], "correct_answer": "D. Fibrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fibrosis Acute pancreatitis is characterized by inflammation, edema, and fat necrosis in the pancreas , which can be seen on histological examination. However, fibrosis is not typically a histological feature of acute pancreatitis. Instead, fibrosis may develop over time as a result of recurrent or chronic pancreatitis.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological features of acute pancreatitis typically include: Inflammation : The pancreas shows infiltration of inflammatory cells such as neutrophils, lymphocytes, and macrophages. Edema : The pancreas shows interstitial edema, which is the accumulation of fluid between cells. Necrosis : The pancreas shows necrosis of pancreatic parenchymal cells, which can result in the release of digestive enzymes and other toxins into the surrounding tissue. Fat necrosis : The pancreas shows fat necrosis, which is the breakdown of fat cells and the release of fatty acids into the surrounding tissue. This can cause further inflammation and damage to the pancreas. Haemorrhage : The pancreas may show areas of haemorrhage, which is the accumulation of blood within the tissue.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 32-year-old patient underwent renal Biopsy for nephrotic syndrome. Along with glomerular pathology, arterioles show the lesions as depicted in the histopathological picture. Identify the lesion:", "options": [{"label": "A", "text": "Hyperplastic Arteriolosclerosis", "correct": false}, {"label": "B", "text": "Mönckeberg Medial Sclerosis", "correct": false}, {"label": "C", "text": "Hyaline arteriolosclerosis", "correct": true}, {"label": "D", "text": "Atherosclerosis", "correct": false}], "correct_answer": "C. Hyaline arteriolosclerosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689155760596-QTDP089001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hyaline arteriolosclerosis</p>\n<p><strong>Highyeild:</strong></p><p>Hyaline arteriolosclerosis . Arterioles show homogeneous, pink hyaline thickening with associated luminal narrowing . These changes reflect both plasma protein leakage across injured endothelial cells, as well as increased smooth muscle cell matrix synthesis in response to the chronic hemodynamic stresses of hypertension.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hyperplastic Arteriolosclerosis. Etiology: Malignant HTN Microscopy: Fibrinoid necrosis , concentrically laminated thinking of vessel wall, due to duplication of the basement membrane, deposition of collagen and smooth muscle cells. Option: B. Mönckeberg Medial Sclerosis. Dystrophic calcification of Tunica media and internal elastic media, asymptomatic. Option: D. Atherosclerosis. Atherosclerotic plaques have four principal components: (1) cells including variable numbers of Smooth Muscle Cells , macrophages , and T lymphocytes ; (2) ECM including collagen , elastic fibres , and proteoglycans ; (3) intracellular and extracellular lipids ; and (4) calcifications in later stage plaques.</p>\n<p><strong>Extraedge:</strong></p><p>Etiology: Benign HTN, DM Microscopy: Smooth pink deposition and smooth muscle proliferation.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 54-year-old male patient with an irregular intake of hypertensive medication underwent renal biopsy for hypertension-induced decreased renal function and arterioles shows changes as depicted in the picture. What's your diagnosis?", "options": [{"label": "A", "text": "Hyperplastic Arteriolosclerosis", "correct": true}, {"label": "B", "text": "Mönckeberg medial Sclerosis", "correct": false}, {"label": "C", "text": "Hyaline arteriolosclerosis", "correct": false}, {"label": "D", "text": "Atherosclerosis", "correct": false}], "correct_answer": "A. Hyperplastic Arteriolosclerosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689155761453-QTDP089002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hyperplastic Arteriolosclerosis As patient is hypertensive and histopath image is given which gives the diagnosis of hyperplastic arteriosclerosis.</p>\n<p><strong>Highyeild:</strong></p><p>Hyperplastic Arteriolosclerosis This lesion occurs in severe hypertension ; vessels exhibit concentric, laminated (“onion skin”) thickening of the walls with luminal narrowing . The laminations consist of Smooth Muscle Cells with thickened, reduplicated basement membranes; in malignant hypertension, they are accompanied by fibrinoid deposits and vessel wall necrosis (necrotizing arteriolitis) , particularly in the kidney.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Mönckeberg medial Sclerosis. Dystrophic calcification of Tunica media and internal elastic media, asymptomatic. Option: C. Hyaline arteriolosclerosis. Arterioles show homogeneous, pink hyaline thickening with associated luminal narrowing . Etiology: Benign HTN, DM Microscopy: Smooth pink deposition and smooth muscle proliferation. Option: D. Atherosclerosis. Atherosclerotic plaques have four principal components: (1) cells including variable numbers of Smooth Muscle Cells , macrophages , and T lymphocytes ; (2) ECM including collagen , elastic fibres , and proteoglycans ; (3) intracellular and extracellular lipids ; and (4) calcifications in later stage plaques.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Mönckeberg medial sclerosis except:", "options": [{"label": "A", "text": "Usually seen in old age", "correct": false}, {"label": "B", "text": "It's a type of calcification in media", "correct": false}, {"label": "C", "text": "It can lead to vascular occlusion and medical emergency", "correct": true}, {"label": "D", "text": "Seen in walls of muscular arteries, typically involving the internal elastic membrane", "correct": false}], "correct_answer": "C. It can lead to vascular occlusion and medical emergency", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It can lead to vascular occlusion and medical emergency The calcifications do NOT encroach on the vessel lumen and are usually not clinically significant .</p>\n<p><strong>Highyeild:</strong></p><p>Mönckeberg medial sclerosis is characterized by calcification of the walls of muscular arteries , typically involving the internal elastic membrane. Persons older than age 50 are most commonly affected.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Usually seen in old age. Correct . Option: B. It’s a type of calcification in media. Correct . Option: D. Seen in walls of muscular arteries, typically involving the internal elastic membrane. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The calcifications do NOT encroach on the vessel lumen and are usually not clinically significant . Dystrophic calcification of Tunica media and internal elastic media, asymptomatic.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Defective phagolysosome is a feature of:", "options": [{"label": "A", "text": "Chronic Granulomatous Disease", "correct": false}, {"label": "B", "text": "Chediak Higashi Syndrome", "correct": true}, {"label": "C", "text": "Ataxia telangiectasia", "correct": false}, {"label": "D", "text": "Fanconi Anemia", "correct": false}], "correct_answer": "B. Chediak Higashi Syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Chediak Higashi Syndrome</p>\n<p><strong>Highyeild:</strong></p><p>Chediak Higashi Syndrome Autosomal recessive . Defect in the LYST gene (chromosome 1) Inherited defects in phagolysosome formation . Defective fusion of phagosomes and lysosomes , resulting in defective phagocytes function and susceptibility to infections . Leukocytes contain giant granules , which can be readily seen in peripheral blood smears</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Chronic Granulomatous Disease. Is an X-linked recessive disorder characterized by defects in bacterial killing that render patients susceptible to recurrent bacterial infection . Option: C. Ataxia telangiectasia. Is an autosomal recessive disorder caused by defects in ATM , a gene encoding a kinase that acts upstream of p53. This syndrome is characterized by neurodegeneration (particularly of the cerebellum, hence the ataxia), immunodeficiency, hypersensitivity to radiation (due to an inability to repair double-stranded DNA breaks), and predisposition to cancer, particularly certain forms of leukaemia and lymphoma. Option: D. Fanconi Anemia. Is an autosomal recessive disorder caused by mutations in a pathway that repairs DNA cross-links through homologous recombination . It is characterized by developmental abnormalities (short stature, skeletal abnormalities), hypersensitivity to chemotherapeutic agents that cross-link DNA, and an increased risk of bone marrow failure (aplasia) and leukaemia .</p>\n<p><strong>Extraedge:</strong></p><p>Defective degranulation of : platelets impaired clot formation and excessive bleeding etc. WBC: Neutropenia , increases in fection risk Platelets: Increased bleeding tendencies Melanasomes: Albinism</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Not true about cancer cachexia:", "options": [{"label": "A", "text": "Equal loss of both fat and lean muscle", "correct": false}, {"label": "B", "text": "Elevated basal metabolic rate", "correct": false}, {"label": "C", "text": "No evidence of systemic inflammation", "correct": true}, {"label": "D", "text": "TNFα cachectin plays an important role", "correct": false}], "correct_answer": "C. No evidence of systemic inflammation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>No evidence of systemic inflammation</p>\n<p><strong>Highyeild:</strong></p><p>Cancer cachexia: Cancer cachexia is a hypercatabolic state defined by a loss of muscle mass (with or without loss of fat) that cannot be explained by diminished food intake . Individuals with cancer commonly suffer progressive loss of body fat and lean body mass accompanied by profound weakness, anorexia, and anemia , referred to as cachexia . Cancer cachexia is associated with the following: Equal loss of both fat and lean muscle Elevated basal metabolic rate Evidence of systemic inflammation Inflammation related to the interplay between cancer and the immune system will likely have a role. The precise causes of cancer cachexia are unknown, but inflammatory mediators, particularly TNFα, IL-1, and IL-6 , appear to have essential roles.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Equal loss of both fat and lean muscle. True . Option: B. Elevated basal metabolic rate. True . Option: D. TNFα (cachectin) plays an important role. True .</p>\n<p><strong>Extraedge:</strong></p><p>TNFα (known initially as cachectin ) is a leading suspect among several mediators released from immune cells that may contribute to cachexia. However, it must also be recognized that therapies directed against individual cytokines (e.g., TNF) in cancer patients have not been effective in reversing cachexia, suggesting that either an assortment of inflammatory cytokines, or other factors entirely, are also involved in its pathogenesis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following are epithelial tumours of the? Granulosa cell tumour Brenner tumour Serous tumour Endometrioid tumors Dysgerminoma Select the correct answer from given below code:", "options": [{"label": "A", "text": "2,3,4", "correct": true}, {"label": "B", "text": "1,3,5", "correct": false}, {"label": "C", "text": "3,4,5", "correct": false}, {"label": "D", "text": "1,4,5", "correct": false}], "correct_answer": "A. 2,3,4", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>2,3,4 Among the given options, epithelial cell tumours include: Brenner tumour Serous tumour Endometrioid tumour</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - 1. Granulosa cell tumour - It is a sex cord tumour 5. Dysgerminoma - It is a germ-cell tumour</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the histological features of complex branching patterns and widespread infiltration or effacement of the underlying stroma, Identify the type of ovarian tumour:", "options": [{"label": "A", "text": "Serous carcinoma", "correct": true}, {"label": "B", "text": "Mucinous carcinoma", "correct": false}, {"label": "C", "text": "Brenner tumour", "correct": false}, {"label": "D", "text": "Endometrioid carcinoma", "correct": false}], "correct_answer": "A. Serous carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161037033-QTDP157002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serous carcinoma The given histopathological image of the ovarian tumour showing a complex branching pattern and widespread infiltration or effacement of the underlying stroma is suggestive of Serous carcinoma of the ovary. It is an ovarian epithelial tumour, tumor cells often form papillary structures, which can have a branching or complex pattern.</p>\n<p><strong>Highyeild:</strong></p><p>Serous Carcinoma Origin : Epithelial cells lining the surface of the ovary High-grade tumour : aggressive and rapidly progressing Histology: Papillary Growth Pattern : Tumor cells form finger-like projections or papillae that extend into the cystic spaces or cover the ovarian surface. Complex Branching Pattern: The papillae can show various degrees of complexity, with multiple layers and fronds. Psammoma bodies may be present Stromatolites infiltration and nuclear atypia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Mucinous carcinoma: It is another type of ovarian epithelial tumour characterized by glandular structures containing mucin. Option: C. Brenner tumours: These are typically composed of transitional epithelium and are characterized by nests of epithelial cells with coffee bean nuclei. Option: D. Endometrioid carcinoma: It is a type of ovarian epithelial tumour that resembles the endometrium and is associated with endometriosis. It may show glandular or cribriform structures but does not typically exhibit the specific complex branching pattern mentioned in the case.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Mutation of which gene is most commonly seen in mucinous tumours of the ovary:", "options": [{"label": "A", "text": "PTEN", "correct": false}, {"label": "B", "text": "KRAS", "correct": true}, {"label": "C", "text": "TP53", "correct": false}, {"label": "D", "text": "BRAF", "correct": false}], "correct_answer": "B. KRAS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>KRAS Mutations in the KRAS gene, specifically in codon 12 or 13, are frequently observed in mucinous ovarian tumours. The KRAS gene encodes a protein involved in cell signalling pathways that regulate cell growth and division. Mutations in KRAS result in the activation of downstream signalling pathways, leading to uncontrolled cell proliferation and tumour formation.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. PTEN: It is a tumour suppressor gene involved in regulating cell growth, division, and apoptosis. It is commonly associated with endometrioid and clear cell carcinomas of the ovary but is not frequently seen in mucinous tumours. Option: C. TP53: TP53 mutations are most commonly observed in high-grade serous carcinomas of the ovary rather than mucinous tumours. Option: D. BRAF: BRAF is a proto-oncogene that plays a role in regulating cell signalling pathways. Mutations in the BRAF gene are more commonly associated with other types of cancer, such as melanoma and thyroid cancer, rather than mucinous tumours of the ovary.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the histological features in the diagram shown below, identify the type of ovarian tumour:", "options": [{"label": "A", "text": "Brenner tumour", "correct": false}, {"label": "B", "text": "Serous carcinoma", "correct": false}, {"label": "C", "text": "Mucinous carcinoma", "correct": false}, {"label": "D", "text": "Teratoma", "correct": true}], "correct_answer": "D. Teratoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161037996-QTDP157005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Teratoma The given histopathological image shows the cyst wall composed of stratified squamous epithelium with underlying sebaceous glands is suggestive of Teratoma . Teratomas are germ cell tumours that can contain various tissue types derived from different germ cell layers . They often exhibit diverse elements such as skin, hair, sebaceous glands, and other adnexal structure</p>\n<p><strong>Highyeild:</strong></p><p>Mature cystic teratoma Also called a dermoid cyst Benign Most common ovarian tumour in young females Cystic mass with elements from all 3 germ layers (teeth, hair, sebum) May be painful secondary to ovarian enlargement or torsion Malignant transformation rare: Squamous cell carcinoma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Brenner tumour: It is typically composed of transitional epithelium and is characterized by the presence of nests of epithelial cells with coffee bean nuclei. Option: B. Serous carcinoma: It is an ovarian epithelial tumour characterized by the presence of papillary structures and psammoma bodies. Option: C. Mucinous carcinoma: It is an ovarian epithelial tumour characterized by glandular structures containing mucin</p>\n<p><strong>Extraedge:</strong></p><p>Immature Vs Mature teratoma Immature teratoma Mature teratoma Type Malignant tumour Typically benign tumour Histology Presence of immature tissue elements Presence of well-differentiated tissue elements Components Immature tissues such as neuroepithelial elements, embryonal structures Mature tissues representing various germ cells layers, such as skin, hair, teeth, and glands Clinical behaviour Aggressive behaviour with the potential for metastasis Typically localized and does not metastasize Serum tumour markers May show elevated levels of tumour markers such as AFP and beta-hCG Tumour markers are usually not elevated</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 24-year-old female patient presented with raised chorionic gonadotropin and adnexal mass. Excision of the mass done and histology shows large vesicular cells with abundant clear cytoplasm and fibrous septa containing lymphocytic infiltrate as shown in the diagram, so based on the above features what’s your diagnosis?", "options": [{"label": "A", "text": "Choriocarcinoma", "correct": false}, {"label": "B", "text": "Teratoma", "correct": false}, {"label": "C", "text": "Dysgerminoma", "correct": true}, {"label": "D", "text": "Endodermal sinus tumour", "correct": false}], "correct_answer": "C. Dysgerminoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161040374-QTDP157009IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dysgerminoma The given histopathological image showing large vesicular cells having a clear cytoplasm, well-defined cell boundaries , and centrally placed regular nuclei is suggestive of Dysgerminoma It is a type of germ cell tumour that commonly occurs in young females. It is associated with elevated serum levels of chorionic gonadotropin (hCG).</p>\n<p><strong>Highyeild:</strong></p><p>Dysgerminoma It is a type of germ-cell tumour Malignant Most common in adolescents Equivalent to male seminoma but rarer Histology: Sheets of Large Cells ( fried egg cells ) Lymphocytic Infiltrate Often exhibit nuclear grooves Abundant Mitotic Figures Lacks Vascular Invasion IHC: OCT 3/4, NANOG, PLAP, and CD117 (c-kit).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Choriocarcinoma: it is another type of malignant germ cell tumour characterized by the presence of syncytiotrophoblasts and cytotrophoblasts. Option: B. Teratoma: It is a germ cell tumour that can contain various tissue types derived from different germ layers. Option: D. Endodermal sinus tumour: These tumours are associated with elevated levels of alpha-fetoprotein (AFP), not chorionic gonadotropin (hCG) as described in the case.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 20-year-old female presents with lower abdominal pain and a palpable mass. Imaging reveals a solid ovarian tumour with areas of haemorrhage and necrosis. Laboratory investigations show elevated levels of alpha-fetoprotein (AFP). Which of the following is the most likely diagnosis?", "options": [{"label": "A", "text": "Endodermal sinus tumour", "correct": true}, {"label": "B", "text": "Teratoma", "correct": false}, {"label": "C", "text": "Dysgerminoma", "correct": false}, {"label": "D", "text": "Embryonal carcinoma", "correct": false}], "correct_answer": "A. Endodermal sinus tumour", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Endodermal sinus tumour The given clinical history is suggestive of an Endodermal sinus tumour or yolk sac tumour. These are aggressive germ cell tumours that commonly occur in young females and are associated with elevated AFP levels.</p>\n<p><strong>Highyeild:</strong></p><p>Yolk sac tumour Aka Endodermal sinus tumour Malignant and aggressive Often occurs in children and young adult females Histology: Schiller-Duval bodies: small, glomerulus-like structures composed of central blood vessels surrounded by tumour cells. Primitive endodermal differentiation: Tumour marker: Increased AFP</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:B. Mucinous cystadenoma: It is a benign ovarian tumour that is characterized by the presence of mucin-filled cysts. They typically present as multiloculated cystic masses without solid components. Option:C. Serous cystadenoma: It is also a benign ovarian tumour that predominantly consists of serous fluid-filled cysts. They usually do not exhibit solid areas or haemorrhage/necrosis in imaging studies. Option:D. Granulosa cell tumour: It is an ovarian tumour that arises from the granulosa cells of the ovarian follicles. Granulosa cell tumours are associated with elevated levels of estrogen, which can result in hormonal manifestations like breast enlargement and precocious puberty.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 55-year-old female patient has a large adnexal mass with raised inhibin levels. Histopathology shows cord and sheets of tumour cells, often showing nuclear grooves as shown in the diagram, based on the above clinical features identify the type of tumour:", "options": [{"label": "A", "text": "Choriocarcinoma", "correct": false}, {"label": "B", "text": "Granulosa cell tumor", "correct": true}, {"label": "C", "text": "Yolk sac tumour", "correct": false}, {"label": "D", "text": "Leidig cell tumour", "correct": false}], "correct_answer": "B. Granulosa cell tumor", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161043164-QTDP157012IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Granulosa cell tumor The given clinical history with a histopathological image showing cord and sheets of tumour cell, often showing nuclear groove /coffee-bean-like nuclei ( Call-exner bodies ) is suggestive of Granulosa cell tumour. These are sex cord-stromal tumours of the ovary which can produce inhibin</p>\n<p><strong>Highyeild:</strong></p><p>Granulosa cell tumour Most common malignant sex cord-stromal tumour Age: 50 years age Presents with Post-menopausal bleeding Endometrial hyperplasia Sexual precocity Breast tenderness Histology: Call-exner bodies Tumour marker: Increased inhibin</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Choriocarcinoma: It is a germ cell tumour that is characterized by the presence of syncytiotrophoblasts and cytotrophoblasts. It is associated with elevated levels of beta-human chorionic gonadotropin (β-hCG), rather than inhibin. Option: C. Yolk sac tumour: It is another germ cell tumour that typically presents with elevated serum levels of alpha-fetoprotein (AFP). Option: D. Leydig cell tumours: These are Leydig cell tumours and are associated with the production of androgens, rather than inhibin.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which gene is most commonly mutated in granulosa cell tumours?", "options": [{"label": "A", "text": "FOXP 3", "correct": false}, {"label": "B", "text": "FOXL2", "correct": true}, {"label": "C", "text": "SOX 1", "correct": false}, {"label": "D", "text": "SOX 11", "correct": false}], "correct_answer": "B. FOXL2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FOXL2 In granulosa cell tumours (GCTs), the most commonly mutated gene is FOXL2 . FOXL2 is a transcription factor gene that plays a crucial role in Granulosa cell development. The majority of adult-type GCTs, including both juvenile and adult variants, are associated with a specific mutation in the FOXL2 gene.</p>\n<p><strong>Highyeild:</strong></p><p>Granulosa cell tumour Most common malignant sex cord-stromal tumour Age: 50 years age Presents with Post-menopausal bleeding Endometrial hyperplasia Sexual precocity Breast tenderness Histology: Call-exner bodies Tumour marker: Increased inhibin</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A. FOXP3: It is a gene that encodes a transcription factor called forkhead box P3. Mutations in the FOXP3 gene are associated with a rare genetic disorder called immune dysregulation, polyendocrinopathy, enteropathy, and X-linked syndrome (IPEX syndrome). Option:C. SOX1: It is a gene that belongs to the SOX (SRY-related HMG-box) family of transcription factors. Mutations in the SOX1 gene have been implicated in the development of certain types of cancers, including esophageal squamous cell carcinoma and lung adenocarcinoma. Option:D. SOX11: It is another gene belonging to the SOX family of transcription factors. It plays a role in embryonic development and tissue differentiation. Mutations or dysregulation of SOX11 have been implicated in various types of cancers, including B-cell lymphomas.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 50-year-old female presents with a large Aden exam mass and abdominal discomfort. Ovary was removed and on histopathology, Reinke crystalloids were found. What is the likely diagnosis?", "options": [{"label": "A", "text": "Granulosa cell tumour", "correct": false}, {"label": "B", "text": "Gonadoblastoma", "correct": false}, {"label": "C", "text": "Hilus cell tumour", "correct": true}, {"label": "D", "text": "Yolk sac tumour", "correct": false}], "correct_answer": "C. Hilus cell tumour", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161044896-QTDP157016IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hilus cell tumour The given clinical scenario with a histopathological image showing reinke crystals is suggestive of Hilus cell tumour, also known as Leydig cell tumour. These are rare sex cord-stromal tumours of the ovary and are often hormonally active, leading to the production of androgens, which can cause virilization symptoms.</p>\n<p><strong>Highyeild:</strong></p><p>Leydig cell tumour It is a sex-cord tumour Benign Hormonally active and can produce excessive amounts of testosterone or other androgens Androgens are responsible for virilization Gross : Well-circumscribed, solid , and yellowish to golden-brown in colour Histology: Reinke Crystals: intracytoplasmic crystalloid structures Polyhedral cells: Polygonal or spindle-shaped cells with eosinophilic cytoplasm Abundant Lipid Droplets</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Granulosa cell tumours: These are another type of sex cord-stromal tumour of the ovary, but they typically present with estrogenic symptoms rather than androgenic symptoms. Option: B . Gonadoblastoma: It is a mixed germ cell and sex cord-stromal tumour and is often associated with disorders of sexual development. Option: D. Yolk sac tumour: It is a germ cell tumour that typically occurs in young females and is associated with elevated serum levels of alpha-fetoprotein.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 19 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding post-streptococcal glomerulonephritis except", "options": [{"label": "A", "text": "It is usually seen in children 6 to 10 years of age", "correct": false}, {"label": "B", "text": "It is caused by all β-hemolytic strains of streptococcal bacteria", "correct": true}, {"label": "C", "text": "It is an immune complex-mediated disease", "correct": false}, {"label": "D", "text": "Serum complement levels are low", "correct": false}], "correct_answer": "B. It is caused by all β-hemolytic strains of streptococcal bacteria", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is caused by all β-hemolytic strains of streptococcal bacteria Post-streptococcal glomerulonephritis (PSGN) is a type of glomerulonephritis that occurs as a result of an infection with certain strains of group A beta-hemolytic streptococci , Only certain strains of group A β-hemolytic strepto-cocci are nephritogenic, with more than 90% of cases being traced to types 12, 4, and 1, which can be identified by typing of the M protein of the bacterial cell walls.</p>\n<p><strong>Highyeild:</strong></p><p>Post-streptococcal glomerulonephritis Aka infection-associated glomerulonephritis Type III hypersensitivity reaction Age: Seen in children Cause: Group Streptococcus (strain 12,4,1). In adults can also be caused by Staphylococcus. Seen 2 to 4 weeks after pharyngeal or skin infection Associated with hypocomplementemia (due to consumption). Microscopic features can persist for 1 to 2 years -Diagnosis: LM: Glomeruli enlarged and hypercellular IF: Granular or starry sky appearance- “Lumpy-bumpy” due to deposition of IgG, IgM and C3 along GBM and mesangium EM: Subepithelial IC humps - Prognosis: children- excellent prognosis, Adults- worse prognosis This glomerulus is hypercellular and capillary loops are poorly defined. This is a type of proliferative glomerulonephritis known as post-infectious glomerulonephritis. (low power microscopy)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is usually seen in children 6 to 10 years of age: True. PSGN is most common in children between the ages of 6 and 10, but it can occur at any age. Option: C. It is an immune complex-mediated disease: True. PSGN is an immune complex-mediated disease, in which immune complexes become deposited in the glomeruli, leading to an inflammatory response and damage to the glomeruli. Option: D. Serum complement levels are low: True. In PSGN, serum complement levels (C3 in particular) are typically low, due to the consumption of complement during the immune response to the streptococcal infection.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are the histological features of post-streptococcal glomerulonephritis except:", "options": [{"label": "A", "text": "Infiltration of leukocytes into the glomerulus", "correct": false}, {"label": "B", "text": "Proliferation of mesangial and endothelial cells", "correct": false}, {"label": "C", "text": "Proliferation and infiltration into glomerulus are focal and segmental", "correct": true}, {"label": "D", "text": "Glomerulus enlarges in size", "correct": false}], "correct_answer": "C. Proliferation and infiltration into glomerulus are focal and segmental", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Proliferation and infiltration into glomerulus are focal and segmental Proliferation and infiltration into the glomerulus are diffuse and global, not focal and segmental, in post-streptococcal glomerulonephritis (PSGN).</p>\n<p><strong>Highyeild:</strong></p><p>Histological features of PSGN: Enlarged glomeruli : It becomes enlarged due to the inflammatory response. Hypercellularity : The glomeruli show an increase in the number of cells due to the proliferation of mesangial cells and endothelial cells. Infiltration of leukocytes: There is an infiltration of neutrophils and monocytes into the glomeruli, causing inflammation. \" Lumpy-bumpy\" appearance : PSGN is often described as having a \"lumpy-bumpy\" appearance on light microscopy, due to the presence of subepithelial and intramembranous deposits of immune complexes. Diffuse involvement of glomeruli is seen.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Immunofluorescence microscopy in streptococcal glomerulonephritis characteristically demonstrates deposition of all except:", "options": [{"label": "A", "text": "IgG", "correct": false}, {"label": "B", "text": "C-3", "correct": false}, {"label": "C", "text": "IgM", "correct": false}, {"label": "D", "text": "IgA", "correct": true}], "correct_answer": "D. IgA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IgA Immunofluorescence microscopy in post-streptococcal glomerulonephritis characteristically demonstrates granular deposition of IgG, C-3, and IgM in a diffuse pattern in the mesangium and along the capillary loops . The deposition of these immune complexes causes an inflammatory response leading to glomerular damage and subsequent nephritis. IgA deposition is not typically seen in post-streptococcal glomerulonephritis.</p>\n<p><strong>Highyeild:</strong></p><p>Post-streptococcal glomerulonephritis Aka infection-associated glomerulonephritis Type III hypersensitivity reaction Age: Seen in children Cause: Group A streptococcus (strain 12,4,1). In adults can also be caused by Staphylococcus. Seen 2 to 4 weeks after pharyngeal or skin infection Associated with hypocomplementemia (due to consumption). Microscopic he matures can persist for 1 to 2 years -Diagnosis: LM: Glomeruli enlarged and hypercellular IF: Granular or starry sky appearance- “Lumpy-bumpy” due to deposition of IgG, IgM and C3 along GBM and mesangium EM: Subepithelial IC humps - Prognosis: children- excellent prognosis, Adults- worse prognosis This glomerulus is hypercellular and capillary loops are poorly defined. This is a type of proliferative glomerulonephritis known as post-infectious glomerulonephritis. (low power microscopy)</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and\n C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement\n membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have\n mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II\n (Dense Deposit Disease) C3 deposition in the dense intramembranous\n deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q\n along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3,\n with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A seven-year-old child had a sore throat 3 to 4 weeks back and presently has chief complaints of fever, malaise and cola colour urine. Renal biopsy is shown below based on the histological features of what's your diagnosis?", "options": [{"label": "A", "text": "RPGN", "correct": false}, {"label": "B", "text": "PSGN", "correct": true}, {"label": "C", "text": "Membranous nephropathy", "correct": false}, {"label": "D", "text": "MPGN", "correct": false}], "correct_answer": "B. PSGN", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689159585385-QTDP136004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PSGN The given clinical history and a histological image showing hypercellular and enlarged glomeruli are suggestive of PSGN (post-streptococcal glomerulonephritis). The history of sore throat 3-4 weeks back, along with fever, malaise, and cola-coloured urine, is consistent with the clinical presentation of PSGN .</p>\n<p><strong>Highyeild:</strong></p><p>Post-streptococcal glomerulonephritis Aka infection-associated glomerulonephritis Type III hypersensitivity reaction Age: Seen in children Cause: Group A streptococcus (strain 12,4,1). In adults can also be caused by Staphylococcus. Seen 2 to 4 weeks after pharyngeal or skin infection Associated with hypocomplementemia (due to consumption). Microscopic he matures can persist for 1 to 2 years -Diagnosis: LM: Glomeruli enlarged and hypercellular IF: Granular or starry sky appearance- “Lumpy-bumpy” due to deposition of IgG, IgM and C3 along GBM and mesangium EM: Subepithelial IC humps - Prognosis: children- excellent prognosis. Adults- worse prognosis This glomerulus is hypercellular and capillary loops are poorly defined. This is a type of proliferative glomerulonephritis known as post-infectious glomerulonephritis. (low power microscopy)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. RPGN: It is characterized by a rapidly progressive decline in renal function and crescent formation in glomeruli on histology. Option: C. Membranous nephropathy: It is characterized by the thickening of the glomerular basement membrane and subepithelial immune complex deposition. Option: D. MPGN: It is characterized by the thickening of the glomerular basement membrane due to mesangial cell proliferation, subendothelial and subepithelial immune complex deposition, and capillary wall splitting.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A true statement regarding post-streptococcal glomerulonephritis is:", "options": [{"label": "A", "text": "Shrunken glomeruli", "correct": false}, {"label": "B", "text": "IgA deposition in mesangium", "correct": false}, {"label": "C", "text": "Subepithelial humps are seen", "correct": true}, {"label": "D", "text": "Mesangiolysis", "correct": false}], "correct_answer": "C. Subepithelial humps are seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Subepithelial humps are seen In PSGN , Subepithelial humps are seen on electron microscopy, which is formed due to the deposition of immune complexes in the subepithelial region of the glomerulus. These humps can cause a characteristic \"lumpy-bumpy\" appearance on the glomerular basement membrane.</p>\n<p><strong>Highyeild:</strong></p><p>Post-streptococcal glomerulonephritis Aka infection-associated glomerulonephritis Type III hypersensitivity reaction Age: Seen in children Cause: Group A streptococcus (strain 12,4,1). In adults can also be caused by Staphylococcus. Seen 2 to 4 weeks after pharyngeal or skin infection Associated with hypocomplementemia (due to consumption). Microscopic he matures can persist for 1 to 2 years -Diagnosis: LM: Glomeruli enlarged and hypercellular IF: Granular or starry sky appearance- “Lumpy-bumpy” due to deposition of IgG, IgM and C3 along GBM and mesangium EM: Subepithelial IC humps Prognosis: children- excellent prognosis, Adults- worse prognosis This glomerulus is hypercellular and capillary loops are poorly defined. This is a type of proliferative glomerulonephritis known as post-infectious glomerulonephritis. (low power microscopy)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Shrunken glomeruli: This is not a typical finding in PSGN. Instead, glomerular enlargement is seen in PSGN due to cellular proliferation and increased mesangial matrix. Option: B. IgA deposition in mesangium: This finding is associated with IgA nephropathy, not PSGN. Option: D. Mesangiolysis: This is not a typical finding in PSGN. Instead, PSGN is characterized by mesangial hypercellularity and expansion.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Immunofluorescence findings of various types of glomerulonephritis: Glomerulonephritis IF findings Minimal Change Disease Negative Focal Segmental Glomerulosclerosis Negative or segmental deposits of IgM, C3, and\n C1q Membranous Nephropathy Granular IgG and C3 along the glomerular basement\n membrane IgA Nephropathy Granular mesangial IgA and C3 Membranoproliferative Glomerulonephritis Type I Granular subendothelial IgG and C3; may also have\n mesangial and subepithelial deposits Membranoproliferative Glomerulonephritis Type II\n (Dense Deposit Disease) C3 deposition in the dense intramembranous\n deposits Post-Streptococcal Glomerulonephritis Granular IgG, C3, and occasionally IgM and C1q\n along the glomerular basement membrane and mesangium Rapidly Progressive Glomerulonephritis Variable, depending on the underlying cause Lupus Nephritis Granular deposits of IgG, IgM, IgA, C1q, and C3,\n with different patterns depending on the class of lupus nephritis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding serous cystic neoplasm of the pancreas except:", "options": [{"label": "A", "text": "It is usually located in the tail", "correct": false}, {"label": "B", "text": "It is multicystic and contains clear, thin, straw-coloured fluid", "correct": false}, {"label": "C", "text": "It is a malignant tumour of the pancreas", "correct": true}, {"label": "D", "text": "Inactivation of the VHL gene is seen", "correct": false}], "correct_answer": "C. It is a malignant tumour of the pancreas", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is a malignant tumour of the pancreas Serous cystic neoplasm of the pancreas is a benign tumour and is typically located in the tail of the pancreas.</p>\n<p><strong>Highyeild:</strong></p><p>Serous cystic neoplasms of the pancreas Aka serous cystadenoma These are benign tumours that typically occur in middle-aged women. Site: Typically located in the tail of the pancreas Genetic abnormality: Inactivation of the VHL tumour suppressor gene Histopathology: The cysts are small (1 to 3 mm), lined by glycogen-rich cuboidal cells, and contain clear, thin, straw-coloured fluid Treatment: Surgical resection</p>\n<p><strong>Table:</strong></p><p>Cystic\n neoplasms of the pancreas Characteristics Serous cystadenoma Mucinous cystadenoma Intraductal papillary mucinous neoplasm Incidence 60-70 years, Females Young females Elderly males Pathology Benign 30% risk of malignancy 65% risk of malignancy at 5 years Appearance Microcysts <2cm; Usually >6 in number, Central Stella the scar present Larger cysts, septations present Pleomorphic, nodules present, fish mouth\n appearance Calcification Central calcification Peripheral eggshell calcification Rare H a emorrhage Rare Rare Rare Pancreatic duct Normal Dilatation +/- Dilated, communication + Epithelium Glycogen-rich, cuboidal Columnar, mucin-producing Columnar, mucin-producing Aspirate Low CEA, amylase High CEA, Low amylase High CEA, High amylase</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are oncogenes mutated in pancreatic carcinoma except:", "options": [{"label": "A", "text": "KRAS", "correct": false}, {"label": "B", "text": "AKT 2", "correct": false}, {"label": "C", "text": "MYB", "correct": false}, {"label": "D", "text": "SMAD 4", "correct": true}], "correct_answer": "D. SMAD 4", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>SMAD 4 SMAD4 is not an oncogene but a tumour suppressor gene that is commonly inactivated in pancreatic cancer.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. KRAS: It is an oncogene that is frequently mutated in pancreatic cancer. It is a GTPase that plays a key role in signal transduction pathways involved in cell growth and proliferation. Mutations in the KRAS gene are found in up to 90% of pancreatic ductal adenocarcinomas and are believed to be an early event in the development of the disease. Option: B. AKT2: It is another oncogene that is commonly mutated in pancreatic cancer. It is a serine/threonine kinase that regulates several downstream signalling pathways involved in cell survival and proliferation. Amplification or overexpression of the AKT2 gene has been observed in approximately 30% of pancreatic ductal adenocarcinomas and is associated with a more aggressive tumour phenotype. Option: C. MYB: It is an oncogene that is commonly mutated in pancreatic cancer. It is a proto-oncogene that is involved in regulating cell growth and differentiation in several different tissues. Myb promotes pancreatic cancer cell growth, clonogenicity, migration and invasion.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding pancreatic carcinoma except:", "options": [{"label": "A", "text": "Predominantly seen in old age", "correct": false}, {"label": "B", "text": "Cigarette smoking and diabetes are risk factors", "correct": false}, {"label": "C", "text": "The most favoured location is tail", "correct": true}, {"label": "D", "text": "Germline mutation can be seen in BRCA 2 and CDKN2A", "correct": false}], "correct_answer": "C. The most favoured location is tail", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The most favoured location is tail Pancreatic carcinoma is most commonly seen in the head of the pancreas and not in the tail.</p>\n<p><strong>Highyeild:</strong></p><p>Pancreatic adenocarcinoma Very aggressive tumour arising from pancreatic ducts It is more commonly seen in older individuals, with the highest incidence occurring in the 7th decade of life. Germline mutation can be seen in BRCA 2 and CDKN2A Risk factors: Tobacco smoking (strongest risk factor) Chronic pancreatitis Diabetes Age >50 years Location : Most commonly located in the head of the pancreas, followed by the body and tail Symptoms : Painless jaundice, weight loss, abdominal pain, and new onset diabetes.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 74-year-old patient presented with jaundice and a mass lesion in the head region of the pancreas in a CT scan. Biopsy from the lesion demonstrates as shown in the diagram. Based on the histological features what is your diagnosis?", "options": [{"label": "A", "text": "Adenocarcinoma", "correct": true}, {"label": "B", "text": "Squamous cell carcinoma", "correct": false}, {"label": "C", "text": "Lymphoma", "correct": false}, {"label": "D", "text": "Angiosarcoma", "correct": false}], "correct_answer": "A. Adenocarcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689159173103-QTDP132006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adenocarcinoma The given clinical history and an image showing glands lined by pleomorphic cuboidal-to-columnar epithelial cells suggest the diagnosis of Adenocarcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Pancreatic adenocarcinoma Very aggressive tumour arising from pancreatic ducts It is more commonly seen in older individuals, with the highest incidence occurring in the 7th decade of life. Germline mutation can be seen in BRCA 2 and CDKN2A Risk factors: Tobacco smoking (strongest risk factor) Chronic pancreatitis Diabetes Age >50 years Location : Most commonly located in the head of the pancreas, followed by the body and tail Symptoms : Painless jaundice, weight loss, abdominal pain, and new onset diabetes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Squamous cell carcinoma: SCC of the pancreas is a very rare entity and accounts for less than 1% of pancreatic malignancies. It is characterized by the presence of nests, cords, and sheets of squamous cells that show keratinization. Option: C. Lymphoma: It is also rare and accounts for less than 1% of all pancreatic tumours. Histologically, it is characterized by the proliferation of lymphoid cells with varying degrees of differentiation. Option: D. Angiosarcoma: It is extremely rare and is characterized by the proliferation of atypical endothelial cells that form vascular channels. It typically presents with haemorrhage and necrosis.</p>\n<p><strong>Extraedge:</strong></p><p>Histopathology of pancreatic adenocarcinoma: Glands formed by pleomorphic cuboidal-to-columnar epithelial cells arranged in irregular clusters or cords Prominent nucleoli Mitotic figures Desmoplastic stroma with infiltrating inflammatory cells Invasive growth into surrounding tissues</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following does not progress to carcinoma?", "options": [{"label": "A", "text": "Bowen’s disease", "correct": false}, {"label": "B", "text": "Bowenoid papulosis", "correct": true}, {"label": "C", "text": "Leukoplakia", "correct": false}, {"label": "D", "text": "Erythroplakia", "correct": false}], "correct_answer": "B. Bowenoid papulosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bowenoid papulosis Bowenoid papulosis is a sexually transmitted disease caused by human papillomavirus (HPV) that presents as red-brown papules in the genital area and does not progress to carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Bowenoid papulosis Seen predominantly in young, sexually active males. Solitary or multiple, rapidly growing, red-brown to violaceous, flat-topped papules that may coalesce into larger plaques on the penile shaft or the perineum. The papules are nonpruritic , range in size from 2- 10 mm, and usually lack scale Histopathology: Bowenoid papulosis shows the typical features of Bowen's disease. Full-thickness epidermal atypia with crowding and an irregular, \" windblown\" arrangement of the nuclei, many of which are large, hyperchromatic, and pleomorphic Dyskeratotic and multinucleated keratinocytes are also present, as are atypical mitoses. The basement membrane is intact.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Bowen's disease: It is a type of squamous cell carcinoma in situ, which means it has not yet invaded the underlying tissue. Without treatment, Bowen's disease can progress to invasive squamous cell carcinoma. Option: C. Leukoplakia: It is a condition characterized by white patches on the mucous membranes of the mouth, tongue, or gums. While leukoplakia itself is not cancerous, it can be a precancerous lesion that has the potential to progress to squamous cell carcinoma if left untreated. Option: D. Erythroplakia: It is a red patch that can occur on the mucous membranes of the mouth, tongue, or gums. Like leukoplakia, erythroplakia is a precancerous lesion that can progress to squamous cell carcinoma if left untreated.</p>\n<p><strong>Extraedge:</strong></p><p>Pre-malignant lesions of Invasive Penile SCC: Erythroplasia of Queyrat Condyloma accuminata Bowen’s disease</p>\n<p><strong>Table:</strong></p><p>Bowen’s disease Vs Bowenoid papulosis Features Bowen’s disease (carcinoma in\n situ) Bowenoid papulosis Age >30 years <30 years Lesion Solitary, Gray-white Multiple, reddish brown Progression Increase risk of invasive\n Squamous cell carcinoma Does not progress to invasive\n Squamous cell carcinoma Visceral malignancies Increased risk of visceral\n malignancies No Histology Carcinoma in situ (HPV-16) Same as Bowen’s (HPV-16)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A sexually active young man presented with multiple polypoid growths over his penis. Histopathological findings from an excised lesion show papillary architecture with acanthosis, hyperkeratosis and koilocytosis of squamous epithelium. What is the likely diagnosis?", "options": [{"label": "A", "text": "Condyloma lata", "correct": false}, {"label": "B", "text": "Bowen’s disease", "correct": false}, {"label": "C", "text": "Condyloma accuminata", "correct": true}, {"label": "D", "text": "Verrucous carcinoma", "correct": false}], "correct_answer": "C. Condyloma accuminata", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Condyloma accuminata The given clinical history is suggestive of Condyloma accuminata. It is a sexually transmitted infection caused by human papillomavirus (HPV) and commonly presents as multiple papillary growths on the penis, perineum, and perianal area. Histologically , it shows papillary architecture with acanthosis, hyperkeratosis, and koilocytosis of squamous epithelium.</p>\n<p><strong>Highyeild:</strong></p><p>Condyloma accuminata condyloma lata caused by HPV 6>11 Treponema pallidum- Secondary syphilis Easily bleeds on touch No bleeding Rough, verrucous, dry flat and moist soft, pedunculated induration, sessile Dark ground examination: Negative positive Treatment: Podophyllum resin 25% in alcohol Penicillin</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Condyloma lata: It is a manifestation of secondary syphilis and presents as flat-topped papules in the anogenital area. Option: B. Bowen’s disease: It is a form of squamous cell carcinoma in situ that presents as a single scaly, erythematous patch or plaque with irregular borders. Option: D. Verrucous carcinoma: It is a subtype of squamous cell carcinoma that presents as a large, exophytic, cauliflower-like mass, usually on the genitalia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Large homogenous eosinophilic inclusions in plasma cells are called:", "options": [{"label": "A", "text": "Dutcher bodies", "correct": false}, {"label": "B", "text": "Councilman bodies", "correct": false}, {"label": "C", "text": "Russell bodies", "correct": true}, {"label": "D", "text": "Mallory hyaline bodies", "correct": false}], "correct_answer": "C. Russell bodies", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Russell bodies The globular inclusions in the plasma cells are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear) .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Dutcher bodies.Large homogenous eosinophilic inclusions in the nucleus of plasma cells are called Dutcher bodies . Option: B. Councilman bodies. Councilman body , also known as a Councilman hyaline body or apoptotic body , is an eosinophilic globule of apoptotic hepatocyte cell fragments, seen in Yellow fever . Option: D. Mallory hyaline bodies. Mallory’s body, Mallory-Denk’s body, and Mallory's hyaline are an inclusion found in the cytoplasm of liver cells. Mallory bodies are damaged intermediate filaments within the liver cells.</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The single most important predictor of survival in multiple myeloma:", "options": [{"label": "A", "text": "IL-6 levels", "correct": false}, {"label": "B", "text": "Bence jones proteinuria", "correct": false}, {"label": "C", "text": "CD 138 Positivity", "correct": false}, {"label": "D", "text": "Serum β2 microglobulin", "correct": true}], "correct_answer": "D. Serum β2 microglobulin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serum β2 microglobulin Serum β2 -microglobulin is the single most powerful predictor of survival and can substitute for staging . β2-Microglobulin concentration is the strongest and most reliable prognostic factor for multiple myeloma. It depends not only on the tumour burden but also on renal function . Elevated β2-M values predict early death.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. IL-6 levels. Incorrect . Option: B. Bence jones proteinuria. Incorrect . Option: C. CD 138 positivity. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False statement about monoclonal gammopathy of unknown significance", "options": [{"label": "A", "text": "< 3g/dL of monoclonal protein", "correct": false}, {"label": "B", "text": "No bence jones proteinuria", "correct": false}, {"label": "C", "text": "Bone marrow plasma cells < 10%", "correct": false}, {"label": "D", "text": "Does not progress to multiple myeloma", "correct": true}], "correct_answer": "D. Does not progress to multiple myeloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Does not progress to multiple myeloma 1% monoclonal gammopathy of unknown significance progresses to multiple myeloma every year . MGUS (Monoclonal Gammopathy of Undetermined Significance): MGUS is the most common plasma cell disorder No Bence Jones proteinuria seen. No organ impairment. M protein < 3 g/dL Bone marrow plasma cells < 10% Patients are asymptomatic Can progress to Multiple Myeloma. As with smouldering myeloma, progression to multiple myeloma is unpredictable; hence, periodic assessment of serum M component levels and Bence Jones proteinuria is warranted.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. < 3g/dL of monoclonal protein. Correct . Option: B. No bence jones proteinuria. Correct . Option: C. Bone marrow plasma cells < 10%. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Multiple myeloma is a tumour of:", "options": [{"label": "A", "text": "B-lymphocyte", "correct": false}, {"label": "B", "text": "T-lymphocyte", "correct": false}, {"label": "C", "text": "Lymph nodes", "correct": false}, {"label": "D", "text": "Plasma cell", "correct": true}], "correct_answer": "D. Plasma cell", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Plasma cell Multiple myeloma is a malignant proliferation of plasma cel ls derived from a single clone .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. B-lymphocyte. Incorrect . Option: B. T-lymphocyte. Incorrect . Option: C. Lymph nodes. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A patient presents with bone pain. X-ray reveals destructive lesions. Lab investigations show hypercalcemia. Serum electrophoresis shows an M spike, while Bone marrow shows 35% plasma cells. What is your diagnosis?", "options": [{"label": "A", "text": "MGUS", "correct": false}, {"label": "B", "text": "Smoldering myeloma", "correct": false}, {"label": "C", "text": "Multiple myeloma", "correct": true}, {"label": "D", "text": "Plasma cell leukaemia", "correct": false}], "correct_answer": "C. Multiple myeloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple myeloma In the given scenario, the patient has bone pain , destructive bony lesions on X-Ray , hypercalcemia , M spike and 35% plasma cells in the Bone marrow which is diagnostic of Multiple Myeloma .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. MGUS. M protein is < 3.5 g/dL, Plasma cells in the bone marrow are < 10% and the patient is asymptomatic. Option: B. Smoldering myeloma. M protein is > 3.5 g/dL, Plasma cells in the bone marrow are > 10% and the patient is asymptomatic. Option: D. Plasma cell leukaemia. Rarely when tumour cells flood the peripheral blood , it gives rise to plasma cell leukaemia.</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Beta-2 –microglobulin is a tumour marker for-", "options": [{"label": "A", "text": "Multiple myeloma", "correct": true}, {"label": "B", "text": "Lung cancer", "correct": false}, {"label": "C", "text": "Colonic neoplasm", "correct": false}, {"label": "D", "text": "Choriocarcinoma", "correct": false}], "correct_answer": "A. Multiple myeloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple myeloma The tumour marker for multiple myeloma is Serum β2 microglobulin Serum β2 microglobulin level < 3.5mg/L indicates a good prognosis Serum β2 microglobulin is the single most powerful predictor of survival and can substitute for staging . β2-Microglobulin concentration is the strongest and most reliable prognostic factor for multiple myeloma. It depends not only on the tumour burden but also on renal function . Elevated β2-M values predict early death.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Lung cancer. CEA, EGFR, TP53, RAS etc are tumour markers for different types of lung cancer. Option: C. Colonic neoplasm. CEA, CA 19-9, EGFR, TP53, RAS etc are tumour markers for Colon cancer. Option: D. HCG is a tumour marker for Choriocarcinoma.</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Proliferation and survival of myeloma cells are dependent on which of the following cytokines?", "options": [{"label": "A", "text": "IL-1", "correct": false}, {"label": "B", "text": "IL-6", "correct": true}, {"label": "C", "text": "IL-2", "correct": false}, {"label": "D", "text": "IL-5", "correct": false}], "correct_answer": "B. IL-6", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IL-6 IL-6 helps in the survival and proliferation of myeloma cells. The proliferation and survival of myeloma cells are dependent on several cytokines , most notably IL-6 , which is an important growth factor for plasma cells . It is produced by the tumour cells themselves and by resident marrow stromal cells . High serum levels of IL-6 are seen in patients with active disease and are associated with a poor prognosis .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. IL-1. Incorrect . Option: C. IL-2. Incorrect . Option: D. IL-5. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "For Multiple myeloma, all are true, except:", "options": [{"label": "A", "text": "Proteinuria", "correct": false}, {"label": "B", "text": "Visual disturbance", "correct": false}, {"label": "C", "text": "Bleeding", "correct": false}, {"label": "D", "text": "Dystrophic calcification", "correct": true}], "correct_answer": "D. Dystrophic calcification", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dystrophic calcification Calcification in multiple myeloma is due to hypercalcemia ( metastatic calcification ) and not dystrophic calcification.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Proteinuria. Correct . Option: B. Visual disturbance. Correct , In Multiple myeloma, paraproteins are formed which can cause hyperviscosity of blood leading to visual symptoms. Option: C. Bleeding. Correct , Bleeding tendencies in multiple myeloma can be explained by a variety of mechanisms such as dysfibrinogenemia, paraprotein-induced platelet dysfunction, shortened platelet survival, damage to the vascular endothelium, and acquired von Willebrand syndrome .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Dystrophic calcification: Deposition of calcium at sites of cell injury and necrosis .\n Occurs despite normal serum levels of calcium and in the absence of\n derangements in calcium metabolism. Metastatic calcification: Deposition of\n calcium in normal tissues, caused by hypercalcemia secondary to some disturbance in calcium\n metabolism . Features Dystrophic Calcification Metastatic Calcification Location Occurs in dead and dying\n tissue Occurs in live tissue Calcium metabolism Normal Abnormal metabolism, leading\n to Hypercalcemia Examples Atheromatous plaque Rheumatic vegetations Monckeberg Medial Sclerosis TB lymph node Psammoma bodies - Foci of dystrophic calcification Asbestos bodies Vitamin D intoxication Parathyroid tumours Multiple myeloma Paget’s disease Milk alkali syndrome Sarcoidosis Renal failure Hypercalcemia of malignancy Stains used for Calcium: · Von-Kossa stain · Alizarin Red S Calcium in H & E is intensely basophilic.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Bence Jones proteinuria is derived from:", "options": [{"label": "A", "text": "Alpha globulins", "correct": false}, {"label": "B", "text": "Light chain globulins", "correct": true}, {"label": "C", "text": "Gamma globulins", "correct": false}, {"label": "D", "text": "Delta globulins", "correct": false}], "correct_answer": "B. Light chain globulins", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Light chain globulins The Excretion of light chains in the urine has been referred to as Bence Jones proteinuria . Light chains include κ and λ (kappa and lambda)</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Alpha globulins. Incorrect . Option: C. Gamma globulins. Incorrect . Option: D. Delta globulins. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Malignancy associated with Waldenstrom macroglobulinemia:", "options": [{"label": "A", "text": "Mycosis fungoides", "correct": false}, {"label": "B", "text": "Smoldering myeloma", "correct": false}, {"label": "C", "text": "Primary effusion lymphoma", "correct": false}, {"label": "D", "text": "Lymphoplasmacytic lymphoma", "correct": true}], "correct_answer": "D. Lymphoplasmacytic lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphoplasmacytic lymphoma Lymphoplasmacytic lymphoma: Lymphoplasmacytic lymphoma is a B-cell neoplasm of older adults that usually presents in the sixth or seventh decade of life . Although superficially resembling CLL/SLL, it differs in that a substantial fraction of the tumour cells undergo terminal differentiation to plasma cells . Most commonly, the plasma cell component secretes monoclonal IgM , often in amounts sufficient to cause a hyperviscosity syndrome known as Waldenström macroglobulinemia . Unlike multiple myeloma, complications stemming from the secretion of free light chains (e.g. Renal failure and amyloidosis) are relatively rare, and bone destruction does NOT occur .</p>\n<p><strong>Highyeild:</strong></p><p>Mutation: MYD 88 Most common genetic abnormality: Deletion of 6q Patients with IgM-secreting tumours have additional signs and symptoms stemming from the physicochemical properties of IgM. It gives rise to a hyperviscosity syndrome characterized by the following: Visual impairment associated with venous congestion, reflected by striking tortuosity and distention of retinal veins; retinal haemorrhages and exudates may also contribute to visual problems. Neurologic problems such as headaches, dizziness, deafness, and stupor, all stemming from sluggish blood flow. Bleeding is related to the formation of complexes between macroglobulins and clotting factors as well as interference with platelet function. Cryoglobulinemia results from the precipitation of macroglobulins at low temperatures, producing symptoms such as the Raynaud phenomenon and cold urticaria.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Mycosis fungoides. Mycosis fungoides and Sézary syndrome are different manifestations of a tumour of CD4+ helper T cells that are home to the skin. Option: B: Smoldering myeloma. M protein is > 3.5 g/dL, Plasma cells in the bone marrow are > 10% and the patient is asymptomatic. Option: C. Primary effusion lymphoma. Primary effusion lymphoma presents as a malignant pleural or ascitic effusion , mostly in patients with advanced HIV infection or in older adults. The tumour cells are often anaplastic in appearance and typically fail to express surface B- or T-cell markers , but have clonal IGH gene rearrangements . In all cases, the tumour cells are infected with HHV-8, which appears to have a causal role .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The Russel body is seen in -", "options": [{"label": "A", "text": "Lymphocytes", "correct": false}, {"label": "B", "text": "Neutrophils", "correct": false}, {"label": "C", "text": "Macrophages", "correct": false}, {"label": "D", "text": "Plasma cells", "correct": true}], "correct_answer": "D. Plasma cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Plasma cells Russel bodies are seen in Plasma cells Diagnosis of Plasma cell myeloma or Multiple Myeloma Inclusion bodies in plasma cells: Dutcher bodies- Intranuclear Russell bodies- Intracytoplasmic</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Alpha globulins. Incorrect . Option: C. Gamma globulins. Incorrect . Option: D. Delta globulins. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "True about Bence-Jones protein are all except:", "options": [{"label": "A", "text": "Made of light chain", "correct": false}, {"label": "B", "text": "Reappears at 100 degrees C", "correct": true}, {"label": "C", "text": "Dissolve at 100 degrees C", "correct": false}, {"label": "D", "text": "Amyloid light chain in urine", "correct": false}], "correct_answer": "B. Reappears at 100 degrees C", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reappears at 100 degrees C Bence-Jones proteins are made of a light chain , dissolve at 100°C and lead to an Amyloid light chain in urine.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Made of light chain. Correct . Option: C. Dissolve at 100 degrees C. Correct . Option: D. Amyloid light chain in urine. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 70-year-old male has a pathologic fracture of the femur. The lesion appears lytic on X-ray film with a circumscribed punched-out appearance. The curetting from the fracture site is most likely to show which of the following:", "options": [{"label": "A", "text": "Diminished and thinned trabecular bone fragments secondary to osteopenia", "correct": false}, {"label": "B", "text": "Sheets of atypical plasma cells", "correct": true}, {"label": "C", "text": "Metastatic prostatic adenocarcinoma", "correct": false}, {"label": "D", "text": "None of the Above", "correct": false}], "correct_answer": "B. Sheets of atypical plasma cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Sheets of atypical plasma cells The single punched lesion from the femur in an old age person is most likely suggestive of plasma cell neoplasm , so the curettage or biopsy from this area will show sheets of atypical plasma cells .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Diminished and thinned trabecular bone fragments secondary to osteopenia. Osteopenia is defined as a reduction in bone density. The term is often used radiologically when it describes a qualitative appearance of bone on a radiograph . “Circumscribed punched-out appearance” doesn’t go in favour of osteopenia. Option: C. Metastatic prostatic adenocarcinoma. There is no history suggestive of Prostatic carcinoma , moreover, prostatic cancer shows purely Osteoblastic secondaries . Option: D. None of the Above. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is not true-", "options": [{"label": "A", "text": "Patients with IgD myeloma may present with no evident M-spike on serum electrophoresis", "correct": false}, {"label": "B", "text": "A diagnosis of plasma cell leukaemia can be made if circulating peripheral blood plasma blasts comprise 14% of peripheral blood white cell count of 1 X 10^9 / L and platelet count of 88 X 10^9/ L", "correct": true}, {"label": "C", "text": "In smouldering myeloma plasma cells constitute 10 - 30% of total bone marrow cellularity", "correct": false}, {"label": "D", "text": "In a patient with multiple myeloma, monoclonal light chains may be detected in both serum and urine", "correct": false}], "correct_answer": "B. A diagnosis of plasma cell leukaemia can be made if circulating peripheral blood plasma blasts comprise 14% of peripheral blood white cell count of 1 X 10^9 / L and platelet count of 88 X 10^9/ L", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>A diagnosis of plasma cell leukaemia can be made if circulating peripheral blood plasma blasts comprise 14% of peripheral blood white cell count of 1 X 10^9 / L and platelet count of 88 X 10^9/ L False as a diagnosis of plasma cell leukaemia can be made if circulating peripheral blood plasma blasts comprise >20% and not 14% of peripheral blood white cell count.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Patients with IgD myeloma may present with no evident M-spike on serum electrophoresis. True, as patients with IgD myeloma may present as non-secretory myeloma which means no evident M-spike on serum electrophoresis . Option: C. In smoldering myeloma plasma cells constitute 10 - 30% of total bone marrow cellularity. True, as In smouldering myeloma, plasma cells constitute >10% of total bone marrow cellularity . Option: D. In a patient with multiple myeloma, monoclonal light chains may be detected in both serum and urine. True, as in a patient with multiple myeloma, monoclonal light chains may be detected in both serum and urine .</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Not a feature of multiple myeloma:", "options": [{"label": "A", "text": "Hypercalcemia", "correct": false}, {"label": "B", "text": "Anaemia", "correct": false}, {"label": "C", "text": "Hyperviscosity", "correct": false}, {"label": "D", "text": "Elevated alkaline phosphatase", "correct": true}], "correct_answer": "D. Elevated alkaline phosphatase", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Elevated alkaline phosphatase Alkaline Phosphatase levels in multiple myeloma are normal and not raised, as there is no bone formation and only bone lysis . Serum alkaline phosphatase is usually normal even with extensive bone involvement because of the absence of osteoblastic activity .</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hypercalcemia. Seen. Option: B. Anaemia. Seen. Option: C. Hyperviscosity. Seen.</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hyperviscosity is seen in all except:", "options": [{"label": "A", "text": "Cryoglobulinemia", "correct": true}, {"label": "B", "text": "Multiple myeloma", "correct": false}, {"label": "C", "text": "MGUS", "correct": false}, {"label": "D", "text": "Lymphoma", "correct": false}], "correct_answer": "A. Cryoglobulinemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cryoglobulinemia Hyperviscosity is seen in - Multiple myeloma, MGUS, Lymphoma & Macroglobulinemia</p>\n<p><strong>Highyeild:</strong></p><p>Patients with IgM-secreting tumours have additional signs and symptoms stemming from the physicochemical properties of IgM. It gives rise to a hyperviscosity syndrome characterized by the following: Visual impairment associated with venous congestion, reflected by striking tortuosity and distention of retinal veins; retinal haemorrhages and exudates may also contribute to visual problems. Neurologic problems such as headaches, dizziness, deafness, and stupor, all stemming from sluggish blood flow. Bleeding is related to the formation of complexes between macroglobulins and clotting factors as well as interference with platelet function. Cryoglobulinemia results from the precipitation of macroglobulins at low temperatures, producing symptoms such as the Raynaud phenomenon and cold urticaria.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Multiple myeloma. Correct . Option: C. MGUS. Correct . Option: D. Lymphoma. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The cell mass in multiple myeloma is formed by", "options": [{"label": "A", "text": "Clonal expansion of terminally matured B cells", "correct": false}, {"label": "B", "text": "Preformed B cells are seen in the marrow", "correct": false}, {"label": "C", "text": "Circulating B cells settle in BM", "correct": false}, {"label": "D", "text": "B-cells turn malignant and secrete light chains", "correct": true}], "correct_answer": "D. B-cells turn malignant and secrete light chains", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B-cells turn malignant and secrete light chains The cell mass in multiple myeloma is formed by B-cells or Plasma cells, that turn malignant and secrete light chains.</p>\n<p><strong>Highyeild:</strong></p><p>Multiple Myeloma Multiple myeloma is a plasma cell neoplasm commonly associated with lytic bone lesions, hypercalcemia, renal failure, and acquired immune abnormalities. CRAB features are seen: Hyper C alcemia Re nal Failure A naemia B one lytic lesions Multiple myeloma of the skull (radiograph, lateral view). The sharply punched-out bone lesions are most obvious in the calvaria. Multiple myeloma (bone marrow aspirate). Normal marrow cells are largely replaced by plasma cells including forms with multiple nuclei, prominent nucleoli, and cytoplasmic droplets containing immunoglobulin. Multiple myeloma usually presents as destructive plasma cell tumours (plasmacytomas) involving the axial skeleton . The bones most commonly affected (in descending order of frequency) are the vertebral column, ribs, skull , pelvis, femur, clavicle, and scapula The pathogenesis of renal failure , which occurs in up to 50% of patients, is multifactorial . However, the single most important factor seems to be Bence Jones proteinuria , as the excreted light chains are toxic to renal tubular epithelial cells . Certain light chains (particularly those of the λ6 and λ3 families) are prone to cause amyloidosis of the AL type , which can exacerbate renal dysfunction and deposit in other tissues as well. It should be noted, however, that the great majority of myeloma patients who have free light chains in serum and urine do not develop amyloidosis . Cytologic variants stem from the dysregulated synthesis and secretion of Ig , which often leads to intracellular accumulation of intact or partially degraded protein . Such variants include flame cells with fiery red cytoplasm, Mott cells with multiple grapelike cytoplasmic droplets, and cells containing a variety of other inclusions, including fibrils, crystalline rods, and globules. The globular inclusions are referred to as Russell bodies (if cytoplasmic) or Dutcher bodies (if nuclear). Immunophenotyping: CD 38 +ve, CD 138 +ve (syndecan-1), CD 56 +ve, CD 19 -ve, CD 45 -ve.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Clonal expansion of terminally matured B cells. This is not entirely correct in the context of multiple myeloma. In multiple myeloma, the malignant plasma cells that form the cell mass in the bone marrow are derived from B cells, but these B cells are not terminally matured B cells. Option: B. Preformed B cells are seen in the marrow. This statement is not entirely correct. In multiple myeloma, there is an abnormal proliferation of plasma cells, not preformed B cells. However, B cells do play a role in the development of multiple myeloma as they are the precursor cells of plasma cells. Option: C. Circulating B cells settle in BM: This statement is also not correct. While B cells do circulate in the blood, they normally do not settle in the bone marrow. In multiple myeloma, the abnormal plasma cells that form the cell mass in the bone marrow are not derived from circulating B cells that settle in the marrow.</p>\n<p><strong>Extraedge:</strong></p><p>SLIM criteria: S: > Sixty per cent Plasma cells. LI: Light chains > 100 M: MRI ≥ 2 lesions of > 1.5 cm of cells Anyone criterion is enough for diagnosis of Multiple Myeloma</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Not true regarding Waldenstrom's macroglobulinemia is -", "options": [{"label": "A", "text": "Lymphadenopathy is usually present", "correct": false}, {"label": "B", "text": "Blood viscosity increased", "correct": false}, {"label": "C", "text": "IgM immunoglobulin is increased", "correct": false}, {"label": "D", "text": "Hypercalcemia", "correct": true}], "correct_answer": "D. Hypercalcemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hypercalcemia In Waldenstrom's macroglobulinemia, lymphadenopathy is usually present, blood viscosity is increased, and IgM immunoglobulin is increased. Hyperviscosity is seen, but hypercalcemia is usually not seen.</p>\n<p><strong>Highyeild:</strong></p><p>Waldenstrorm’s Macroglobulinemia Malignancy of lymphoplasmacytoid cells that secreted IgM . In contrast to myeloma, the disease was associated with lymphadenopathy and hepatosplenomegaly, but the major clinical manifestation was hyperviscosity syndrome . The disease resembles the related diseases CLL, myeloma, and lymphocytic lymphoma. It originates from a post-germinal centre B cell that has undergone somatic mutations and antigenic selection in the lymphoid follicle and has the characteristics of an IgM-bearing memory B cell. The presence of MYD88 mutation status is now used as a diagnostic test to discriminate WM from marginal zone lymphomas (MZLs), IgM-secreting myeloma, and CLL with plasmacytic differentiation. Like multiple myeloma , the disease involves the bone marrow , but unlike myeloma, it does NOT cause bone lesions or hypercalcemia . Bone marrow shows >10% infiltration with lymphoplasmacytic cells ( surface IgM+, CD19+, CD20+, and CD22+, rarely CD5+, but CD10− and CD23− ) with an increase in the number of mast cells. Physical examination reveals lymphadenopathy and hepatosplenomegaly , and ophthalmoscopic examination may reveal vascular segmentation and dilation of the retinal veins characteristic of hyperviscosity states . Patients may have normocytic, normochromic anaemia , but rouleaux formation and a positive Coombs’ test are much more common than in myeloma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Lymphadenopathy is usually present. True . Option: B. Blood viscosity increased. True . Option: C. IgM immunoglobulin is increased. True .</p>\n<p><strong>Table:</strong></p><p>Plasma\n Cell Neoplasm: Properties Monoclonal Gammopathy of Undetermined\n Significance (MGUS) Smouldering Myeloma Multiple Myeloma/ Plasma Cell Myeloma M protein < 3.5 g/dL > 3.5 g/dL any M protein Plasma cells in Bone marrow < 10% > 10% >10% CRAB features Absent Absent Present</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 28 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following statement are not related to the pathogenesis of idiopathic pulmonary fibrosis", "options": [{"label": "A", "text": "Smoking", "correct": false}, {"label": "B", "text": "Age less than 20 years", "correct": true}, {"label": "C", "text": "Loss of function mutation in TERT and TERC gene", "correct": false}, {"label": "D", "text": "Mutations in genes encoding components of surfactant", "correct": false}], "correct_answer": "B. Age less than 20 years", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Age less than 20 years IPF is a disease of older individuals, rarely appearing before the age of 50 years.</p>\n<p><strong>Highyeild:</strong></p><p>Pathogenesis of Idiopathic Pulmonary Fibrosis</p>\n<p><strong>Extraedge:</strong></p><p>Most important among these is cigarette smoking, which increases the risk of IPF severalfold.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding idiopathic pulmonary fibrosis except:", "options": [{"label": "A", "text": "Plural surfaces are cobblestone in appearance", "correct": false}, {"label": "B", "text": "White areas of fibrosis in the lower lobes", "correct": false}, {"label": "C", "text": "Honeycomb fibrosis", "correct": false}, {"label": "D", "text": "All fibrotic lesions are of the same age", "correct": true}], "correct_answer": "D. All fibrotic lesions are of the same age", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All fibrotic lesions are of the same age The fibrotic lesions in Idiopathic Pulmonary Fibrosis are not of the same age. They show spatial heterogeneity (I.e patchy lesion distribution) and temporal heterogeneity (i.e lesions of different ages side-by-side)</p>\n<p><strong>Highyeild:</strong></p><p>Usual Interstitial Pneumonia Aka Idiopathic Pulmonary Fibrosis It is the most common and characteristic pattern of interstitial lung disease ( 50% of all ILD cases). Men > Women Associated with cigarette smoke in, environmental pollutants, and genetic defects. Clinical features: Progressive dyspnea, cough, fatigue, crackles, clubbing HRCT: Reticular opacities, honeycombing, traction bronchiectasis, and subpleural cysts Histopathology: Gross : Pleural surfaces of the lung are cobblestoned as a result of the retraction of scars along the interlobular septa The cut surface shows firm, rubbery white areas of fibrosis, which occurs preferentially in the lower lobes . Microscopic: Interstitial fibrosis with spatial heterogeneity (I.e patchy lesion distribution) and temporal heterogeneity (i.e lesions of different ages side-by-side) Microscopic honeycombing Fibroblast foci often present Above image: UIP- microscopic honeycombing Above image: UIP-fibroblast focus</p>\n<p><strong>Table:</strong></p><p>Common Interstitial Lung Diseases Findings Idiopathic Pulmonary fibrosis Nonspecific Interstitial Pneumonia Respiratory Bronchiolitis Associated ILD Onset Gradual onset of dyspnea and dry cough Subacute onset of shortness of breath and dry cough. Can be asymptomatic , or have dystopia and\n cough Physical examination Rales and digital clubbing Frequent rales but clubbing is less common Rales are common but clubbing is\n rare Exposure Idiopathic Can be idiopathic but often associated with other\n conditions Strong association with smoking HRCT Bilateral subpleural reticular changes are most\n prominent in the lower lobes. Traction Bronchiectasis. Honeycombing Peripheral subpleural ground glass and reticular\n patterns. Traction Bronchiectasis is common but no\n honeycombing Diffuse patchy centrilobular ground glass\n nodules Histopathology Fibroblast foci, Temporal and spatial heterogeneity Honeycombing Fibrosis is more uniform than\n that in UIP Respiratory bronchiolitis with adjacent\n inflammatory and fibrosing changes. Pigment laden macrophages.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The lung biopsy of a 50-year-old patient is shown below based on the histopathological findings. What is your diagnosis?", "options": [{"label": "A", "text": "UIP", "correct": true}, {"label": "B", "text": "NSIP", "correct": false}, {"label": "C", "text": "Asthma", "correct": false}, {"label": "D", "text": "Desquamative interstitial pneumonia", "correct": false}], "correct_answer": "A. UIP", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689156749601-QTDP108003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>UIP The given histopathological picture showing patchy interstitial fibrosis, showing a honeycomb appearance is suggestive of Usual Interstitial Pneumonia (UIP).</p>\n<p><strong>Highyeild:</strong></p><p>Usual Interstitial Pneumonia Aka Idiopathic Pulmonary Fibrosis It is the most common and characteristic pattern of interstitial lung disease ( 50% of all ILD cases). Men > Women Associated with cigarette smoke in, environmental pollutants, and genetic defects. Clinical features: Progressive dyspnea, cough, fatigue, crackles, clubbing HRCT: Reticular opacities, honeycombing, traction bronchiectasis, and subpleural cysts Histopathology: Gross : Pleural surfaces of the lung are cobblestoned as a result of the retraction of scars along the interlobular septa The cut surface shows firm, rubbery white areas of fibrosis, which occurs preferentially in the lower lobes . Microscopic: Interstitial fibrosis with spatial heterogeneity (I.e patchy lesion distribution) and temporal heterogeneity (i.e lesions of different ages side-by-side) Microscopic honeycombing Fibroblast foci often present Above image: UIP- microscopic honeycombing Above image: UIP-fibroblast focus</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. NSIP (Non-Specific Interstitial Pneumonia): It is characterized by more uniform interstitial inflammation and fibrosis. Option: C. Asthma: It is a chronic inflammatory disease of the airways, and histopathological findings typically show eosinophilic infiltration, goblet cell metaplasia, and subepithelial fibrosis. Option: D. Desquamative Interstitial Pneumonia: It is characterized by the accumulation of macrophages in the alveoli, which can progress to interstitial fibrosis. The histopathological findings in DIP typically show diffuse interstitial inflammation and fibrosis</p>\n<p><strong>Extraedge:</strong></p><p>Smoking-related Interstitial Lung Diseases Desquamative interstitial pneumonia Respiratory bronchiolitis Pulmonary LCH Pulmonary alveolar proteinosis</p>\n<p><strong>Table:</strong></p><p>Common Interstitial Lung Diseases Findings Idiopathic Pulmonary fibrosis Nonspecific Interstitial Pneumonia Respiratory Bronchiolitis Associated ILD Onset Gradual onset of dyspnea and dry cough Subacute onset of shortness of breath and dry cough. Can be asymptomatic , or have dystopia and cough Physical examination Rales and digital clubbing Frequent rales but clubbing is less common Rales are common but clubbing is rare Exposure Idiopathic Can be idiopathic but often associated with other conditions Strong association with smoking HRCT Bilateral subpleural reticular changes are most prominent in the lower lobes. Traction Bronchiectasis. Honeycombing Peripheral subpleural ground glass and reticular patterns. Traction Bronchiectasis is common but no honeycombing Diffuse patchy centrilobular ground glass nodules Histopathology Fibroblast foci, Temporal and spatial heterogeneity Honeycombing Fibrosis is more uniform than that in UIP Respiratory bronchiolitis with adjacent inflammatory and fibrosing changes. Pigment laden macrophages.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following histopathological findings is typically seen in non-specific interstitial pneumonia (NSIP)?", "options": [{"label": "A", "text": "Honeycomb cysts with peripheral subpleural distribution", "correct": false}, {"label": "B", "text": "Homogeneous interstitial infiltrate of lymphocytes, plasma cells, and macrophages", "correct": true}, {"label": "C", "text": "Granulomatous inflammation with non-caseating epithelioid cell granulomas", "correct": false}, {"label": "D", "text": "Diffuse alveolar damage with hyaline membrane formation", "correct": false}], "correct_answer": "B. Homogeneous interstitial infiltrate of lymphocytes, plasma cells, and macrophages", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Homogeneous interstitial infiltrate of lymphocytes, plasma cells, and macrophages Non-specific interstitial pneumonia (NSIP) is a form of interstitial lung disease characterized by inflammation and fibrosis within the lung tissue. The cellular patternconsists primarily of mild to moderate chronic interstitial inflammation, containing lymphocytes and a few plasma cells, in auniform or patchy distribution.</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological feature of Non-specific interstitial pneumonia (NSIP) Homogeneous interstitial infiltrate of lymphocytes, plasma cells, and macrophages throughout the lung tissue, which can be patchy or diffuse. The absence of honeycomb change is a hallmark of usual interstitial pneumonia (UIP). Diffuse and uniform area of fibrosis Normal to mildly thickened alveolar septa with minimal collagen deposition. Minimal interstitial inflammation or fibrosis in the alveolar ducts, alveolar spaces, and bronchioles.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Honeycomb cysts with peripheral subpleural distribution: These are seen in usual interstitial pneumonia (UIP). Option: C. Granulomatous inflammation with non-caseating epithelioid cell granulomas: These are typically seen in sarcoidosis, which is another ILD that presents with lymphadenopathy and extrapulmonary manifestations. Option: D. Diffuse alveolar damage with hyaline membrane formation: it is seen in acute respiratory distress syndrome (ARDS).</p>\n<p><strong>Extraedge:</strong></p><p>NSIP is usually associated with Connective tissue diseases like Systemic sclerosis OR CREST HRCT findings: GGO in dependent areas with subpleural sparing</p>\n<p><strong>Table:</strong></p><p>Common Interstitial Lung Diseases Findings Idiopathic Pulmonary fibrosis Nonspecific Interstitial Pneumonia Respiratory Bronchiolitis Associated ILD Onset Gradual onset of dyspnea and dry cough Subacute onset of shortness of breath and dry cough. Can be asymptomatic , or have dystopia and cough Physical examination Rales and digital clubbing Frequent rales but clubbing is less common Rales are common but clubbing is rare Exposure Idiopathic Can be idiopathic but often associated with other conditions Strong association with smoking HRCT Bilateral subpleural reticular changes are most prominent in the lower lobes. Traction Bronchiectasis. Honeycombing Peripheral subpleural ground glass and reticular patterns. Traction Bronchiectasis is common but no honeycombing Diffuse patchy centrilobular ground glass nodules Histopathology Fibroblast foci, Temporal and spatial heterogeneity Honeycombing Fibrosis is more uniform than that in UIP Respiratory bronchiolitis with adjacent inflammatory and fibrosing changes. Pigment laden macrophages.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 40-year-old patient presented with complaints of cough and dyspnoea and a chest x-ray demonstrate patchy areas of consolidation. A histopathological examination is shown below. Based on the findings, what is your diagnosis?", "options": [{"label": "A", "text": "Usual interstitial pneumonia", "correct": false}, {"label": "B", "text": "Non-specific interstitial pneumonia", "correct": false}, {"label": "C", "text": "Cryptogenic Organizing Pneumonia", "correct": true}, {"label": "D", "text": "Hyaline membrane disease", "correct": false}], "correct_answer": "C. Cryptogenic Organizing Pneumonia", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689156761724-QTDP108007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cryptogenic Organizing Pneumonia The given clinical scenario with the patient's clinical presentation of cough and dyspnea with patchy areas of consolidation on chest x-ray, and histopathological image showing Masson bodies is suggestive of Cryptogenic Organizing Pneumonia.</p>\n<p><strong>Highyeild:</strong></p><p>Cryptogenic organizing pneumonia (COP) It is a form of interstitial lung disease that is characterized by the presence of granulation tissue within the air spaces, alveolar ducts, and bronchioles, as well as interstitial inflammation and fibrosis. -Features: The onset of symptoms is subacute : Days to weeks Cough, shortness of breath, and fever are usually present -Histopathological findings: Masson bodies : These are fibrous plugs of organizing tissue within the alveolar spaces and are a characteristic feature of COP. Interstitial inflammation: with lymphocytes and plasma cells. Granulation tissue may be present within the alveolar ducts and bronchioles, which can lead to the formation of polyps. Interstitial fibrosis Bronchiolitis obliterans : It is the obliteration of small bronchiolar lumens due to fibrosis and inflammation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Usual interstitial pneumonia: It typically presents with a different radiological pattern characterized by subpleural and basal predominance with honeycombing Option: B. Nonspecific interstitial pneumonia: It presents with a homogeneous interstitial infiltrate of lymphocytes, plasma cells, and macrophages throughout the lung tissue, without the presence of Masson bodies. Option: D. Hyaline membrane disease: It is also known as respiratory distress syndrome, typically affects premature infants, and is characterized by the presence of hyaline membranes lining the alveolar walls.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 60-year-old patient with a history of sepsis now presents with persistent hypoxemia. A diagnosis of ARDS is made. All of the following statements are true regarding histological features of an ARDS except", "options": [{"label": "A", "text": "Diffuse alveolar damage", "correct": false}, {"label": "B", "text": "Type I pneumocyte hyperplasia", "correct": true}, {"label": "C", "text": "Alveolar walls are lined by a hyaline membrane", "correct": false}, {"label": "D", "text": "Granulation tissue usually resolves", "correct": false}], "correct_answer": "B. Type I pneumocyte hyperplasia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Type I pneumocyte hyperplasia Type II pneumocyte hyperplasia is a common finding in ARDS due to the need for regeneration of the damaged type I pneumocytes</p>\n<p><strong>Highyeild:</strong></p><p>Histopathological findings of ARDS Hyaline membranes : These are pink-staining, proteinaceous deposits that form on the inner surface of the alveoli, and are the hallmark of ARDS. Hyaline membranes are formed due to the accumulation of plasma proteins and cellular debris in the alveoli, resulting in damage to the alveolar-capillary barrier. Inflammation : ARDS is characterized by an inflammatory response in the lungs, which is indicated by the presence of neutrophils and macrophages in the alveoli and interstitial spaces. Edema : The alveolar-capillary barrier in the lungs becomes leaky in ARDS, leading to the accumulation of fluid in the alveoli and interstitial spaces, which is known as pulmonary edema. Alveolar damage : The histopathological features of ARDS include damage to the alveolar walls, leading to the collapse of the alveoli and impaired gas exchange in the lungs. Fibrosis : In some cases of ARDS, there may be the development of fibrosis (scarring) in the lungs, which can lead to long-term respiratory problems.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. C.D: All are true.</p>\n<p><strong>Table:</strong></p><p>Phases of ARDS Phase Duration Features Exudative Day 1-7 Alveolar damage, hyaline membrane formation,\n interstitial edema, alveolar flooding, and surfactant depletion Proliferative Day 7-21 Inflammatory cells, fibroblasts, and\n myofibroblasts migrate to the alveoli, leading to fibrosis and collagen\n deposition Fibrotic Beyond day 21 Fibrosis, scarring, and remodeling of the lung\n tissue, leading to irreversible lung damage and impaired gas exchange</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Which of the following is true regarding polycythemia vera?", "options": [{"label": "A", "text": "Raised ESR", "correct": false}, {"label": "B", "text": "Decreased LAP score", "correct": false}, {"label": "C", "text": "Thrombocytopenia", "correct": false}, {"label": "D", "text": "Leukocytosis", "correct": true}], "correct_answer": "D. Leukocytosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leukocytosis Polycythemia vera results in Panmyelosis (an increase in all myeloid components including leukocytes).</p>\n<p><strong>Highyeild:</strong></p><p>Polycythemia Vera Polycythemia denotes an abnormally high number of circulating red cells , usually with a corresponding increase in the haemoglobin level. The most common cause of primary polycythemia is polycythemia vera , a myeloproliferative neoplasm associated with mutations that lead to erythropoietin-independent growth of red cell progenitors . Polycythemia presents with Aquagenic pruritus ie pruritus seen due to warm bath because of Basophil lysis . Secondary causes of Polycythemia include: Hypoxia COPD Smoking Cyanosis heart disease High altitude Tumours Renal Cell carcinoma Hemangioblastoma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Raised ESR. False , in polycythemia vera , ESR is decreased due to a decrease in rouleaux formation or an increase in the RBC surface area to volume ratio . Option: B. Decreased LAP score. False , LAP score is increased Option: C. Thrombocytopenia. False , Thrombocytosis is seen because of Panmyelosis.</p>\n<p><strong>Extraedge:</strong></p><p>Criteria for diagnosis of Polycythemia Vera (PCV): Polycythemia vera (PCV) is characterized by increased marrow production of red cells, granulocytes, and platelets (panmyelosis), but it is the increase in red cells (polycythemia) that is responsible for most of the clinical symptoms. Diagnosis → all 3 major or 2 major + 1 minor Major criteria ↑ RBC mass →Hb> 16.5% (0°) or HCT > 48% →Hb> 16% (9) or HCT > 48% Hypercellular BM with Panmyelosis JAK2 →V617F → Exon 12 mutation Minor criteria Low EPO (to rule out 2° polycythemia)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Polycythemia is not caused by", "options": [{"label": "A", "text": "Renal carcinoma", "correct": false}, {"label": "B", "text": "Liver carcinoma", "correct": false}, {"label": "C", "text": "Cerebellar hemangioma", "correct": false}, {"label": "D", "text": "Lung carcinoma", "correct": true}], "correct_answer": "D. Lung carcinoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lung carcinoma Polycythemia is not caused by Lung Carcinoma .</p>\n<p><strong>Highyeild:</strong></p><p>Polycythemia: Polycythemia denotes an abnormally high number of circulating red cells , usually with a corresponding increase in the haemoglobin level . It may be relative (when there is hemoconcentration due to decreased plasma volume) or absolute (when there is an increase in the total red cell mass). The most common cause of primary polycythemia is polycythemia vera, a myeloproliferative neoplasm associated with mutations that lead to erythropoietin-independent growth of red cell progenitors Pathophysiologic Classification of Polycythemia Relative Reduced plasma volume (hemoconcentration) Absolute Primary (Low Erythropoietin) Polycythemia vera Inherited erythropoietin receptor mutations (rare) Secondary (High Erythropoietin) Compensatory Lung disease High-altitude living Cyanotic heart disease Paraneoplastic Erythropoietin-secreting tumors (e.g., renal cell carcinoma, hepatocellular carcinoma, cerebellar hemangioblastoma) Hemoglobin mutants with high oxygen affinity Inherited defects that stabilize HIF-1α Chuvash polycythemia (homozygous VHL mutations) Prolyl hydroxylase mutations HIF-I α, Hypoxia-induced factor la .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Renal carcinoma. Correct . Option: B. Liver carcinoma. Correct . Option: C. Cerebellar hemangioma. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A Triad of leukoerythroblastosis, teardrop erythrocytes and large platelets is seen in:", "options": [{"label": "A", "text": "Essential thrombocytosis", "correct": false}, {"label": "B", "text": "Primary myelofibrosis", "correct": true}, {"label": "C", "text": "Myelodysplastic syndrome", "correct": false}, {"label": "D", "text": "Chronic Myeloid Leukaemia", "correct": false}], "correct_answer": "B. Primary myelofibrosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Primary myelofibrosis The most characteristic peripheral blood finding in Primary Myelofibrosis (PMF) is myelophthisis , defined by the presence of leukoerythroblastosis (presence of nucleated red blood cells, metamyelocytes, myelocytes, myeloblasts, and megakaryocytes) and dacryocytosis (Teardrop RBCs).</p>\n<p><strong>Highyeild:</strong></p><p>Primary Myelofibrosis: The hallmark of primary myelofibrosis is the development of obliterative marrow fibrosis . The replacement of the marrow by fibrous tissue reduces bone marrow hematopoiesis , leading to cytopenias and extensive extramedullary hematopoiesis . Approximately 90% of cases have activating mutations of JAK2, CALR, or MPL The chief pathologic feature is the extensive deposition of collagen in the marrow by nonneoplastic fibroblasts . The fibrosis displaces hematopoietic elements, including stem cells , from the marrow and eventually leads to marrow failure . Two factors synthesized by megakaryocytes have been implicated: platelet-derived growth factor (PDGF) and TGF-β . As marrow fibrosis progresses, circulating HSCs take up residence in niches in secondary hematopoietic organs , such as the spleen, the liver, and the lymph nodes , leading to the appearance of extramedullary hematopoiesis. Early in the course, the marrow is often hypercellular due to increases in maturing cells of all lineages, a feature similar to PCV. With progression, the marrow becomes more hypocellular and diffusely fibrotic . Clusters of atypical megakaryocytes with unusual nuclear shapes (described as “cloud-like”) are seen, and hematopoietic elements are often found within dilated sinusoids , which is a manifestation of severe architectural distortion caused by fibrosis. Primary myelofibrosis (peripheral blood smear). Two nucleated erythroid precursors and several teardrop-shaped red cells (dacryocytes) are evident. Immature myeloid cells were present in other fields. An identical picture can be seen in other diseases producing marrow distortion and fibrosis. Marrow distortion leads to the premature release of nucleated erythroid and early granulocyte progenitors ( leukoerythroblastosis ), and immature cells also enter the circulation from sites of extramedullary hematopoiesis. Tear-drop-shaped red cells (dacryocytes) , cells that were probably damaged during the birthing process in the fibrotic marrow, are also often seen. Other common, albeit nonspecific, blood findings include abnormally large platelets and basophilia . JAK2 inhibitors are approved to treat this disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Essential thrombocytosis. Criteria of platelets > 4.5 lakhs/micro L and Megakaryocytes not fulfilled. Option: C. Myelodysplastic syndrome. MDS has refractory cytopenia and most commonly presents with hypercellular bone marrow . Option: D. Chronic Myeloid Leukaemia. Peripheral smear shows leukocytosis with the presence of immature myeloid precursors e. shift to left and is associated with basophilia .</p>\n<p><strong>Table:</strong></p><p>Indications of Bone marrow biopsy: · Dry tap (failure to aspirate marrow): Seen in o Aplastic anaemia o Myelofibrosis o Hairy cell leukaemia · Assess bone marrow cellularity: age dependent, normally can\nbe calculated as 100 - age, but should not be below 25%. · Assess metastatic involvement of bone marrow. · Staging of lymphoma: lymphoma which invades BM directly\nbecomes stage IV. · Myeloproliferative neoplasms. · Storage disorders like Gaucher's.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Bone marrow findings in myelofibrosis-", "options": [{"label": "A", "text": "Dry tap (hypocellular)", "correct": true}, {"label": "B", "text": "Megaloblastic cells", "correct": false}, {"label": "C", "text": "Microcytic cells", "correct": false}, {"label": "D", "text": "Thrombocytosis", "correct": false}], "correct_answer": "A. Dry tap (hypocellular)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Dry tap (hypocellular) Bone marrow findings in Myelofibrosis- Dry tap (hypocellular) . In Myelofibrosis bone marrow is replaced by fibrosis , giving a dry tap on bone marrow aspiration necessitating a bone marrow biopsy.</p>\n<p><strong>Highyeild:</strong></p><p>Primary myelofibrosis: The hallmark of primary myelofibrosis is the development of obliterative marrow fibrosis . The replacement of the marrow by fibrous tissue reduces bone marrow hematopoiesis , leading to cytopenias and extensive extramedullary hematopoiesis . Approximately 90% of cases have activating mutations of JAK2, CALR, or MPL . The chief pathologic feature is the extensive deposition of collagen in the marrow by nonneoplastic fibroblasts . The fibrosis displaces hematopoietic elements, including stem cells , from the marrow and eventually leads to marrow failure . Two factors synthesized by megakaryocytes have been implicated: platelet-derived growth factor (PDGF) and TGF-β . As marrow fibrosis progresses, circulating HSCs take up residence in niches in secondary hematopoietic organs , such as the spleen, the liver, and the lymph nodes , leading to the appearance of extramedullary hematopoiesis. Early in the course, the marrow is often hypercellular due to increases in maturing cells of all lineages, a feature similar to PCV. With progression, the marrow becomes more hypocellular and diffusely fibrotic . Clusters of atypical megakaryocytes with unusual nuclear shapes (described as “cloud-like”) are seen, and hematopoietic elements are often found within dilated sinusoids , which is a manifestation of severe architectural distortion caused by fibrosis. Primary myelofibrosis (peripheral blood smear). Two nucleated erythroid precursors and several teardrop-shaped red cells (dacryocytes) are evident. Immature myeloid cells were present in other fields. An identical picture can be seen in other diseases producing marrow distortion and fibrosis. Marrow distortion leads to the premature release of nucleated erythroid and early granulocyte progenitors ( leukoerythroblastosis ), and immature cells also enter the circulation from sites of extramedullary hematopoiesis. Tear-drop-shaped red cells (dacryocytes) , cells that were probably damaged during the birthing process in the fibrotic marrow, are also often seen. Other common, albeit nonspecific, blood findings include abnormally large platelets and basophilia . JAK2 inhibitors are approved to treat this disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Megaloblastic cells. False . Option: C. Microcytic cells. False . Option: D. Thrombocytosis. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Myelofibrosis leading to a dry tap on bone marrow aspiration is seen with which of the following condition?", "options": [{"label": "A", "text": "Burkitt’s lymphoma", "correct": false}, {"label": "B", "text": "Acute erythroLeukaemia", "correct": false}, {"label": "C", "text": "Acute Megakaryocytic Leukaemia", "correct": true}, {"label": "D", "text": "Acute Myelomonocytic Leukaemia", "correct": false}], "correct_answer": "C. Acute Megakaryocytic Leukaemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Acute Megakaryocytic Leukaemia Myelofibrosis leading to a dry tap on bone marrow aspiration is seen with Acute Megakaryocytic Leukaemia. Conditions in which Myelofibrosis is seen are: Primary Myelofibrosis (PMF) Secondary Myelofibrosis: Myeloproliferative Neoplasms- CML, PCV, ET Myeloid Neoplasms- AML M7 (Acute Megakaryocytic Leukaemia) , MDS Hairy cell Leukaemia, Hodgkin’s, Multiple Myeloma Metastasis Granulomatous diseases- TB, Sarcoidosis Autoimmune disease- SLE, Systemic sclerosis Others- Paget’s disease, Renal osteodystrophy, Radiation, HyperPTH</p>\n<p><strong>Highyeild:</strong></p><p>Primary myelofibrosis: The hallmark of primary myelofibrosis is the development of obliterative marrow fibrosis . The replacement of the marrow by fibrous tissue reduces bone marrow hematopoiesis , leading to cytopenias and extensive extramedullary hematopoiesis . Approximately 90% of cases have activating mutations of JAK2, CALR, or MPL . The chief pathologic feature is the extensive deposition of collagen in the marrow by nonneoplastic fibroblasts . The fibrosis displaces hematopoietic elements, including stem cells , from the marrow and eventually leads to marrow failure . Two factors synthesized by megakaryocytes have been implicated: platelet-derived growth factor (PDGF) and TGF-β . As marrow fibrosis progresses, circulating HSCs take up residence in niches in secondary hematopoietic organs , such as the spleen, the liver, and the lymph nodes , leading to the appearance of extramedullary hematopoiesis. Early in the course, the marrow is often hypercellular due to increases in maturing cells of all lineages, a feature similar to PCV. With progression, the marrow becomes more hypocellular and diffusely fibrotic . Clusters of atypical megakaryocytes with unusual nuclear shapes (described as “cloud-like”) are seen, and hematopoietic elements are often found within dilated sinusoids , which is a manifestation of severe architectural distortion caused by fibrosis. Primary myelofibrosis (peripheral blood smear). Two nucleated erythroid precursors and several teardrop-shaped red cells (dacryocytes) are evident. Immature myeloid cells were present in other fields. An identical picture can be seen in other diseases producing marrow distortion and fibrosis. Marrow distortion leads to the premature release of nucleated erythroid and early granulocyte progenitors ( leukoerythroblastosis ), and immature cells also enter the circulation from sites of extramedullary hematopoiesis. Tear-drop-shaped red cells (dacryocytes) , cells that were probably damaged during the birthing process in the fibrotic marrow, are also often seen. Other common, albeit nonspecific, blood findings include abnormally large platelets and basophilia . JAK2 inhibitors are approved to treat this disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Burkitt’s lymphoma. False . Option: B. Acute erythroLeukaemia. False . Option: D. Acute Myelomonocytic Leukaemia. False .</p>\n<p><strong>Table:</strong></p><p>Indications of Bone marrow biopsy: · Dry tap (failure to aspirate marrow): Seen in o Aplastic anaemia o Myelofibrosis o Hairy cell leukaemia · Assess bone marrow cellularity: age dependent, normally can be\ncalculated as 100 - age, but should not be below 25%. · Assess metastatic involvement of bone marrow. · Staging of lymphoma: lymphoma which invades BM directly\nbecomes stage IV. · Myeloproliferative neoplasms. · Storage disorders like Gaucher's.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 13 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "An elderly male with complaints of urinary retention was diagnosed with Prostate carcinoma. Gleason’s grading system is used for prognosis. The score is determined by evaluating which histological feature in prostate cancer.", "options": [{"label": "A", "text": "Tumor size", "correct": false}, {"label": "B", "text": "Lymph node involvement", "correct": false}, {"label": "C", "text": "Mitotic activity", "correct": false}, {"label": "D", "text": "Architectural patterns", "correct": true}], "correct_answer": "D. Architectural patterns", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Architectural patterns The Gleason score in prostate cancer is determined by evaluating the architectural patterns observed in the tumour tissue. The higher the Gleason score, the more aggressive and poorly differentiated the prostate cancer cells are considered to be. It helps in determining the prognosis and guiding treatment decisions for patients with prostate cancer.</p>\n<p><strong>Highyeild:</strong></p><p>Prostatic adenocarcinoma Common in males >50 years old Arises from the peripheral zone or posterior lobe of the prostate Tumour marker: Prostatic acid phosphatase and PSA PSA: Increased total PSA, with a decreased fraction of free PSA Metastasis: Osteoblastic metastasis in the spine (most often which occurs via Bastson venous plexus ) Histologically graded with Gleason grade which is based on glandular architecture</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Tumor size: Tumor size is not directly assessed or considered when determining the Gleason score in prostate cancer. Option: B. Lymph node involvement: Lymph node involvement is not directly assessed when determining the Gleason score. Option: C. Mitotic activity: While mitotic activity is an important factor in assessing the aggressiveness of tumours in general, it is not specifically used to determine the Gleason score in prostate cancer.</p>\n<p><strong>Extraedge:</strong></p><p>Prostate-zones</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the normal upper limit of prostate-specific antigen for a 65 years old male?", "options": [{"label": "A", "text": "2.5 ng/mL", "correct": false}, {"label": "B", "text": "4.5 ng/mL", "correct": true}, {"label": "C", "text": "5.5 ng/mL", "correct": false}, {"label": "D", "text": "6.5 ng/mL", "correct": false}], "correct_answer": "B. 4.5 ng/mL", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>4.5 ng/mL The normal upper limit of prostate-specific antigen (PSA) can vary depending on factors such as age, race, and individual characteristics. However, a commonly used threshold for the normal upper limit of PSA in 65 years old me n without prostate abnormalities is 5 ng/mL</p>\n<p><strong>Highyeild:</strong></p><p>Prostate-specific antigen Product of prostatic epithelium Secreted in semen Older men have higher PSA than younger males Age PSA upper limb (ng/mL) 40-49 years 2.5 50-59 years 3.5 60-69 years 4.5 70-79 years 6.5</p>\n<p><strong>Extraedge:</strong></p><p>Six variants in PSA value Age-specific: raising the PSA threshold in older men improves specificity PSA velocity: Rate of change of PSA with time. According to a BLSA study, a PSA velocity of more than 0.75 ng/mL/year shows increased prostate cancer PSA density: Ratio of serum PSA and volume of prostate Rate of free-to-bound serum PSA Free versus total PSA Pro-PSA</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Germline mutation of MyD88 is associated with:", "options": [{"label": "A", "text": "Goodpastuer syndrome", "correct": false}, {"label": "B", "text": "Pulmonary hypertension", "correct": false}, {"label": "C", "text": "Pulmonary infection", "correct": true}, {"label": "D", "text": "Asthma", "correct": false}], "correct_answer": "C. Pulmonary infection", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pulmonary infection Germline mutation of MyD88 is associated with susceptibility to certain types of infections, particularly those caused by bacteria and fungi. Hence, Option C. Pulmonary infection is correct. MyD88 is a key component of the Toll-like receptor (TLR) signaling pathway, which plays an essential role in innate immunity and the detection of pathogens. Mutations in MyD88 have been identified in individuals with increased susceptibility to infections such as pneumococcal disease, as well as in patients with certain immunodeficiency disorders.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Goodpasture syndrome: It is an autoimmune disease that primarily affects the kidneys and lungs. It is caused by autoantibodies that attack the basement membrane of these organs. Option: B. Pulmonary hypertension: It is a condition in which there is increased blood pressure in the pulmonary arteries.It can be caused by a variety of factors, including genetic mutations, but MyD88 mutations are not known to be associated with this condition. Option: D. Asthma: it is a chronic inflammatory disease of the airways that can cause wheezing, coughing, and difficulty breathing. While asthma has a strong genetic component, MyD88 mutations are not known to be associated with this condition.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A most common cause of community-acquired pneumonia is:", "options": [{"label": "A", "text": "S.pneumoniae", "correct": true}, {"label": "B", "text": "S.aureus", "correct": false}, {"label": "C", "text": "M.pneumoniae", "correct": false}, {"label": "D", "text": "Klebsiella", "correct": false}], "correct_answer": "A. S.pneumoniae", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>S.pneumoniae Streptococcus pneumoniae, or pneumococcus, is the most common cause of community-acquired acute pneumonia.</p>\n<p><strong>Highyeild:</strong></p><p>Community-acquired pneumonia: It may be defined as pneumonia occurring in patients who have not been hospitalized or living in a nursing home during the 2 weeks prior to the onset of symptoms . It develops in the outpatient setting or within 48 hours of admission to a hospital. Risk factors: Increased age Alcoholism Patient with COPD Immunocompromised Environmental factors Malnutrition Smoking Microbiology of CAP S.pneumoniae is the most common causative agent of CAP Bartlett JG. Management of Respiratory Tract Infections 1st Ed Williams & Wilkins Features: Cough: with purulent sputum Pyrexia Consolidation on CXR Raised WBCs</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. S. aureus: While Staphylococcus aureus is a common cause of healthcare-associated pneumonia, it is not a common cause of community-acquired pneumonia (CAP). Option: C. M. pneumoniae: It is an atypical bacteria that can cause pneumonia, but it is not the most common cause of CAP. It is more commonly associated with mild respiratory infections that do not require hospitalization, although severe cases can occur in certain populations, such as young children and immunocompromised individuals. Option: D. Klebsiella: Klebsiella pneumoniae is a gram-negative bacterium that is often associated with healthcare-associated pneumonia, particularly in people with underlying lung disease or who are immunocompromised.</p>\n<p><strong>Extraedge:</strong></p><p>Modified CURB-65 Blood Urea Nitrogen has been removed: So, no testing is required. Grouping is done only on the basis of clinical criteria. DBP = diastolic blood pressure; SBP = systolic blood pressure. \"Defined as a Mental Test Score of 8, or new disorientation in person, place or time. Predicted 30-day mortality: CRB-65 score 0 = 1.2%. CRB-65 score 1 or 2=8.2%. CRB-65 score 3 or 4-31.3%.</p>\n<p><strong>Table:</strong></p><p>CURB-65 Features Points C Confusion 1 U Urea >7 mmol/L 1 R RR>/30 1 B SBP /<90 mmHg OR DBP /< 60 mmHg 1 65 Age >65 1</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 12 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "A 26-year patient having RBC count 2 lakhs/mm3, PCV 30%, and hemoglobin 9.3, what is the type of anemia?", "options": [{"label": "A", "text": "Iron deficiency anemia", "correct": false}, {"label": "B", "text": "Folic acid deficiency anemia", "correct": true}, {"label": "C", "text": "Thalassemia", "correct": false}, {"label": "D", "text": "Sideroblastic anemia", "correct": false}], "correct_answer": "B. Folic acid deficiency anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Folic acid deficiency anemia Hematocrit or Packed cell volume: Ratio of the volume of RBCs to Total volume of blood Hct or PCV = MCV × RBC concentration Now coming back to the question: MCV =PCV/RBC count (in millions) = 30/0.2 = 150 (Increased) MCH= Hb/RBC count = 9.3/ 0.2= 46 (Increased) MCHC= Hb/ PCV = 31 (Normal) Goes in favor of Macrocytic anemia , thus Option: B is correct.</p>\n<p><strong>Highyeild:</strong></p><p>Adult Reference Ranges for Red Cells* Measurement (Units) Men Women Hemoglobin (g/dL) 13.6-17.2 12.0-15.0 Hematocrit (%) 39-49 33-43 Red cell count (×10/µL) 4.3-5.9 3.5-5.0 Reticulocyte count (%) 0.5-1.5 Mean cell volume (fL) 82-96 Mean cell hemoglobin (pg) 27-33 Mean cell hemoglobin concentration (g/dL) 33-37 Red cell distribution width 11.5-14.5 *Reference ranges vary among laboratories. The reference ranges for the laboratory providing the result should always be used in interpreting test results.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Iron deficiency anemia. Example of Microcytic anemia . Option: C. Thalassemia. Example of Microcytic anemia . Option: D. Sideroblastic anemia. Example of Microcytic anemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Identify the predominant abnormally shaped red cell type seen in the peripheral smear given below:", "options": [{"label": "A", "text": "Macrocyte", "correct": false}, {"label": "B", "text": "Acanthocyte", "correct": true}, {"label": "C", "text": "Dacrocyte", "correct": false}, {"label": "D", "text": "Elliptocyte", "correct": false}], "correct_answer": "B. Acanthocyte", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686829031588-QTDP070002IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Acanthocyte Acanthocytes ( Acanthos means spine ) are cells of approximately spherical shape bearing between 2 and 20 spicules that are of unequal length and distributed irregularly over the red cell surface . Some of the spicules have club-shaped rather than pointed ends.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Macrocyte. Large RBC , classically found in megaloblastic anemias , macrocytes are also present in some cases of aplastic anemia, myelodysplastic syndromes, and other dyserythropoietic states . Option: C. Dacrocyte. RBC that is shaped like a teardrop (a \" teardrop cell \"), seen in Iron deficiency anemia, Primary Myelofibrosis, Pernicious anemia, etc. Option: D. Elliptocyte. Elliptocytes are elongated oval-shaped red blood cells, seen in Iron deficiency anemia, Hereditary Elliptocytosis, and Hereditary Pyropoikilocytosis .</p>\n<p><strong>Extraedge:</strong></p><p>Acanthocytes are seen in: Post splenectomy Abetalipoproteinemia Hyposplenism Liver disease</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Spur cells are seen in", "options": [{"label": "A", "text": "Hereditary spherocytosis", "correct": false}, {"label": "B", "text": "G6PD deficiency", "correct": false}, {"label": "C", "text": "Liver disease", "correct": true}, {"label": "D", "text": "Sideroblastic anemia", "correct": false}], "correct_answer": "C. Liver disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Liver disease Acanthocytes ( Acanthos means spine ) aka Spur cells are cells of approximately spherical shape bearing between 2 and 20 spicules that are of unequal length and distributed irregularly over the red cell surface . Some of the spicules have club-shaped rather than pointed ends.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A: Hereditary spherocytosis. Spherocytes are seen. Option: B. G6PD deficiency. Routine staining may reveal polychromasia , representing increased RBC production . So-called bite cells caused by the splenic removal of denatured hemoglobin may be seen. Heinz bodies (denatured hemoglobin) can be seen. Option: D. Sideroblastic anemia. Type of anemia that results from abnormal utilization of iron during erythropoiesis . A hallmark of sideroblastic anemia is the presence of bone marrow ring sideroblasts , erythroblasts with coarse blue granules at Perls staining, due to pathologic iron deposits in mitochondria.</p>\n<p><strong>Extraedge:</strong></p><p>Acanthocytes are seen in: Post splenectomy Abetalipoproteinemia Hyposplenism Liver disease</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Spiculated RBCs with evenly spaced spikes are called:", "options": [{"label": "A", "text": "Acanthocytes", "correct": false}, {"label": "B", "text": "Stomatocytes", "correct": false}, {"label": "C", "text": "Echinocytes", "correct": true}, {"label": "D", "text": "Dacryocytes", "correct": false}], "correct_answer": "C. Echinocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Echinocytes Echinocytes are erythrocytes that have lost their disc shape and are covered with 10–30 short blunt spicules of fairly regular form .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Acanthocytes ( Acanthos means spine ) aka Spur cells . Acanthocytes are seen in: Post splenectomy, Abetalipoproteinemia, Hyposplenism, and Liver disease . Option: B. Stomatocytes. RBCs with a slit-like or “fish-mouth” central pallor . Stomatocytes may be seen in patients with alcoholic liver disease, hereditary stomatocytosis, or Rh null disease , among other conditions. Option: D. Dacryocytes. Dacrocyte. RBC that is shaped like a teardrop (a \" teardrop cell \"), seen in Iron deficiency anemia, Primary Myelofibrosis, Pernicious anemia etc.</p>\n<p><strong>Extraedge:</strong></p><p>Some causes of echinocytosis: Storage artifact Liver disease, particularly with coexisting renal failure Nutritional or other phosphate deficiency Pyruvate kinase deficiency Phosphoglycerate kinase deficiency Aldolase deficiency Decompression phase of diving Haemolytic uraemic syndrome Following burns Following cardiopulmonary bypass Post-transfusion (spheroechinocytes)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Supravital staining is used for:", "options": [{"label": "A", "text": "Nucleated RBCs", "correct": false}, {"label": "B", "text": "Reticulocytes", "correct": true}, {"label": "C", "text": "Basophils", "correct": false}, {"label": "D", "text": "Myeloblasts", "correct": false}], "correct_answer": "B. Reticulocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reticulocytes Supravital staining is used for Reticulocytes Reticulocytes are juvenile red cells that contain remnants of ribosomal RNA that was present in larger amounts in the cytoplasm of the nucleated precursors from which they were derived. Cells staining shades of blue , ‘blue polychromasia’, are unusually young reticulocytes . ‘Blue polychromasia’ is most often seen when there is either an intense erythropoietic drive or when there is extramedullary erythropoiesis, as, for instance, in primary myelofibrosis or carcinomatosis . Supravital Stains for Reticulocytes : New methylene blue Brilliant cresyl blue Azure B</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Nucleated RBCs. Incorrect . Option: C. Basophils. Incorrect . Option: D. Myeloblasts. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>The administration of recombinant erythropoietin can be suspected from a raised reticulocyte count. Erythropoietin causes increased production of erythroblasts and immature reticulocytes , and accelerates their release from the bone marrow into peripheral blood.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Howel-Jolly bodies may be seen after-", "options": [{"label": "A", "text": "Hepatectomy", "correct": false}, {"label": "B", "text": "Splenectomy", "correct": true}, {"label": "C", "text": "Pancreatectomy", "correct": false}, {"label": "D", "text": "Cholecystectomy", "correct": false}], "correct_answer": "B. Splenectomy", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Splenectomy Howell–Jolly Bodies Howell–Jolly bodies are nuclear remnants . They are small, round cytoplasmic inclusions that stain purple on a Romanowsky stain . They are regularly present after splenectomy and when there is splenic atrophy. They may be seen in a small percentage of red cells in pernicious anaemia . Usually, only a few such inclusions are present, but they may be numerous in cases of coeliac disease and in other conditions in which there is splenic atrophy and megaloblastosis . Photomicrograph of a blood film. Postsplenectomy Shows acanthocytes, a target cell and a Howell-Jolly body</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hepatectomy. Incorrect . Option: C. Pancreatectomy. Incorrect . Option: D. Cholecystectomy. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Cabot’s ring is seen in:", "options": [{"label": "A", "text": "Megaloblastic anemia", "correct": true}, {"label": "B", "text": "Sickle cell disease", "correct": false}, {"label": "C", "text": "Iron deficiency anemia", "correct": false}, {"label": "D", "text": "Autoimmune anemia", "correct": false}], "correct_answer": "A. Megaloblastic anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Megaloblastic anemia Cabot’s ring (Mitotic spindle remnants) is seen in Megaloblastic anemia Thalassemia Post splenectomy</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Sickle cell disease. Incorrect . Option: C. Iron deficiency anemia. Incorrect . Option: D. Autoimmune anemia. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "ESR is a very critical investigation in the diagnosis of TB. Which of the following is true about ESR in TB?", "options": [{"label": "A", "text": "No change in ESR", "correct": false}, {"label": "B", "text": "Confirms recovery from TB", "correct": false}, {"label": "C", "text": "ESR is raised because of increased RBC aggregate", "correct": true}, {"label": "D", "text": "ESR is raised due to decreased RBC size", "correct": false}], "correct_answer": "C. ESR is raised because of increased RBC aggregate", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>ESR is raised because of increased RBC aggregate Erythrocyte Sedimentation Rate In TB, ESR is raised because of increased RBC aggregates.</p>\n<p><strong>Highyeild:</strong></p><p>ESR is increased by any cause or focus of inflammation . The rouleaux formation and the red cell clumping that is associated with the increased ESR mainly reflect the concentrations of fibrinogen and other acute-phase proteins (e.g. haptoglobin, caeruloplasmin, α 1 -acid glycoprotein, α 1 -antitrypsin, and CRP).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. No change in ESR. False . Option: B. Confirms recovery from TB. False . Option: D. ESR is raised due to decreased RBC size. False .</p>\n<p><strong>Extraedge:</strong></p><p>Although ESR is a nonspecific phenomenon , its measurement is clinically useful in disorders associated with increased production of acute-phase proteins. In rheumatoid arthritis or tuberculosis, it provides an index of the progress of the disease , and it is of considerable value in the diagnosis of temporal arteritis and polymyalgia rheumatica . An elevated ESR occurs as an early feature in myocardial infarction .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are true about polycythemia vera except:", "options": [{"label": "A", "text": "Increased ESR", "correct": true}, {"label": "B", "text": "Decreased erythropoietin", "correct": false}, {"label": "C", "text": "Increased LAP score", "correct": false}, {"label": "D", "text": "Increased blood volume", "correct": false}], "correct_answer": "A. Increased ESR", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increased ESR In polycythemia vera , ESR is decreased due to a decrease in rouleaux formation or an increase in the RBC surface area to volume ratio .</p>\n<p><strong>Highyeild:</strong></p><p>Polycythemia denotes an abnormally high number of circulating red cells , usually with a corresponding increase in the hemoglobin level. The most common cause of primary polycythemia is polycythemia vera , a myeloproliferative neoplasm associated with mutations that lead to erythropoietin-independent growth of red cell progenitors . Polycythemia presents with Aquagenic pruritus ie pruritus seen due to warm bath because of Basophil lysis . Secondary causes of Polycythemia include: Hypoxia COPD Smoking Cyanosis heart disease High altitude Tumors Renal Cell carcinoma Hemangioblastoma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Decreased erythropoietin. True . Option: C. Increased LAP score. True . Option: D. Increased blood volume. True .</p>\n<p><strong>Extraedge:</strong></p><p>Criteria for diagnosis of Polycythemia Vera (PCV): Polycythemia vera (PCV) is characterized by increased marrow production of red cells, granulocytes, and platelets (panmyelosis), but it is the increase in red cells (polycythemia) that is responsible for most of the clinical symptoms. Diagnosis → all 3 major or 2 major + 1 minor Major criteria ↑ RBC mass →Hb> 16.5% (0°) or HCT > 48% →Hb> 16% (9) or HCT > 48% Hypercellular BM with Panmyelosis JAK2 →V617F → Exon 12 mutation Minor criteria Low EPO (to rule out 2° polycythemia)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following indicates hemolysis?", "options": [{"label": "A", "text": "Target cells", "correct": false}, {"label": "B", "text": "Schistocytes", "correct": true}, {"label": "C", "text": "Acanthocytes", "correct": false}, {"label": "D", "text": "Basophilic stippling", "correct": false}], "correct_answer": "B. Schistocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Schistocytes Schistocytes: Fragmentation syndromes including MicroAngiopathic Haemolytic Anaemia (MAHA) and mechanical hemolytic anemia (but note that schistocytes can be due to dyserythropoietic as well as hemolysis). Photomicrograph of a blood film. Microangiopathic haemolytic anaemia. Shows angular red cell fragments.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Target cells: Seen in Thalassemia, Liver disease, Abetalipoproteinemia, and severe Iron deficiency anemia . Option: C. Acanthocytes: Seen in Hyperlipidemia Option: D. Basophilic stippling: Seen in Abnormal hemoglobin deposition .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Echinocytes are types of:", "options": [{"label": "A", "text": "RBCs", "correct": true}, {"label": "B", "text": "Lymphocytes", "correct": false}, {"label": "C", "text": "Monocytes", "correct": false}, {"label": "D", "text": "Platelets", "correct": false}], "correct_answer": "A. RBCs", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RBCs Echinocytes are types of RBCs Echinocytes : RBCs with numerous short, regular projections from their surface Echinocytes are seen in uremia, premature infants after exchange transfusion, or as artifacts .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Lymphocytes. False . Option: C. Monocytes. False . Option: D. Platelets. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Burr cell is seen in:", "options": [{"label": "A", "text": "Uremia", "correct": true}, {"label": "B", "text": "Hepatocellular carcinoma", "correct": false}, {"label": "C", "text": "Gastric carcinoma", "correct": false}, {"label": "D", "text": "Ovarian carcinoma", "correct": false}], "correct_answer": "A. Uremia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Uremia Crenated cells in renal disease are called Burr cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Hepatocellular carcinoma. False . Option: C. Gastric carcinoma. False . Option: D. Ovarian carcinoma. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The largest number of bone marrow cells are -", "options": [{"label": "A", "text": "Promyelocytes", "correct": false}, {"label": "B", "text": "Metamyelocytes", "correct": false}, {"label": "C", "text": "Erythroid cells", "correct": true}, {"label": "D", "text": "Myelocytes", "correct": false}], "correct_answer": "C. Erythroid cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Erythroid cells Largest number of bone marrow cells are Erythroid cells . Normal ranges for differential counts on bone marrow aspirate Cell type Normal range Cell type Normal range Myeloblasts 0-3 Eosinophils 03-4 Promyelocytes 3-12 Basophils 0-0.5 Myelocytes (neutrophil) 2-13 Lymphocytes 5-20 Metamyelocytes 2-6 Monocytes 0-3 Neutrophils 22-46 Plasma cells 0-3.5 Myelocytes (eosinophil 0-3 Erythroblasts 5-35 Megakaryocytes 0-2</p>\n<p><strong>Highyeild:</strong></p><p>Indications of Bone marrow biopsy: Dry tap Aplastic anemia (Bone marrow cellularity < 25%) Myelofibrosis Hairy cell leukemia To assess Bone marrow cellularity To assess metastatic involvement of Bone marrow For Lymphoma staging Myeproloferatlibe neoplasms Storage disease such as Gaucher’s</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Promyelocytes. False . Option: B. Metamyelocytes. False . Option: D. Myelocytes. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following proteins binds with free hemoglobin in the plasma:", "options": [{"label": "A", "text": "Albumin", "correct": false}, {"label": "B", "text": "Haptoglobin", "correct": true}, {"label": "C", "text": "Pre-albumin", "correct": false}, {"label": "D", "text": "Ceruloplasmin", "correct": false}], "correct_answer": "B. Haptoglobin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Haptoglobin Haptoglobin binds with free hemoglobin in the plasma Free hemoglobin released from lysed red cells is promptly bound by haptoglobin , producing a complex that is rapidly cleared by mononuclear phagocytes. As serum haptoglobin is depleted , free hemoglobin oxidizes to methemoglobin, which is brown in color.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Albumin binds to Bilirubin . Option: C. Pre-albumin. Pre-albumin binds to the Thyroid hormone . Option: D. Ceruloplasmin binds to Copper .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The best method for hemoglobin estimation is-", "options": [{"label": "A", "text": "Sahli’s hemoglobinometer", "correct": false}, {"label": "B", "text": "Cyanmethaemoglobin method", "correct": true}, {"label": "C", "text": "Calorimetric method", "correct": false}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "B. Cyanmethaemoglobin method", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cyanmethaemoglobin method Best method for hemoglobin estimation is the Cyanmethaemoglobin method Cyanmethemoglobin method is the internationally recommended method for determining the hemoglobin concentration of blood. The basis of the method is the dilution of blood in a solution containing potassium cyanide and potassium ferricyanide, where Hemoglobin is converted to HiCN. The absorbance of the solution is then measured in a spectrometer at a wavelength of 540 nm or a photoelectric colorimeter with a yellow-green filter.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Sahli’s hemoglobinometer. Sahli’s acid haematin method is less accurate because the colour develops slowly, is unstable, and begins to fade almost immediately after it reaches its peak. Option: C. Calorimetric method. The calorimetric method of hemoglobin determination in the blood is described which combines the methods of Sahli and Palmer . The hemoglobin of whole blood is changed to acid hematin with HCl and compared with a standard in a calorimeter. Option: D. None of the above. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "ESR is decreased in all the following conditions except", "options": [{"label": "A", "text": "Polycythemia", "correct": false}, {"label": "B", "text": "Sickle cell anemia", "correct": false}, {"label": "C", "text": "Hyperviscosity", "correct": false}, {"label": "D", "text": "Multiple myeloma", "correct": true}], "correct_answer": "D. Multiple myeloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple myeloma Lower ESR: Extreme leukocytosis Polycythemia Spherocytosis, microcytosis, Sickle cells Hyperviscosity Low Protein; fibrinogen, gamma globulins Technical factors; dilution, clotted sample Afibrinogenemia</p>\n<p><strong>Highyeild:</strong></p><p>Vacutainer tubes: Colours, anticoagulants and uses</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Polycythemia. Low ESR . Option: B. Sickle cell anemia. Low ESR . Option: C. Hyperviscosity. Low ESR .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "ESR is increased in:", "options": [{"label": "A", "text": "Sickle cell anemia", "correct": false}, {"label": "B", "text": "Multiple myeloma", "correct": true}, {"label": "C", "text": "Polycythemia vera", "correct": false}, {"label": "D", "text": "Thalassemia", "correct": false}], "correct_answer": "B. Multiple myeloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple myeloma Increased ESR: Old age Female Pregnancy Anemia Paraprotein (Multiple Myeloma) Hypergammaglobulinemia Macrocytosis Elevated fibrinogen (infection, inflammation, malignancy)</p>\n<p><strong>Highyeild:</strong></p><p>Vacutainer tubes: Colours, anticoagulants and uses</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Sickle cell anemia. Low ESR . Option: C. Polycythemia vera. Low ESR . Option: D. Thalassemia. Low ESR .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "ESR depends on all of the following except:", "options": [{"label": "A", "text": "Viscosity", "correct": false}, {"label": "B", "text": "Fibrinogen", "correct": false}, {"label": "C", "text": "Verticality of tube", "correct": false}, {"label": "D", "text": "Body mass index", "correct": true}], "correct_answer": "D. Body mass index", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Body mass index ESR depends on Viscosity , Fibrinogen , Rouleaux formation & Verticality of the tube but not on whether the patient is obese (i.e. Body mass index or BMI).</p>\n<p><strong>Highyeild:</strong></p><p>ESR is increased by any cause or focus of inflammation . The rouleaux formation and the red cell clumping that is associated with the increased ESR mainly reflect the concentrations of fibrinogen and other acute-phase proteins (e.g. haptoglobin, caeruloplasmin, α 1 -acid glycoprotein, α 1 -antitrypsin, and CRP). Although ESR is a nonspecific phenomenon , its measurement is clinically useful in disorders associated with increased production of acute-phase proteins. In rheumatoid arthritis or tuberculosis, it provides an index of the progress of the disease , and it is of considerable value in the diagnosis of temporal arteritis and polymyalgia rheumatica . An elevated ESR occurs as an early feature in myocardial infarction .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Viscosity. Correct . Option: B. Fibrinogen. Correct . Option: C. Verticality of the tube. Correct .</p>\n<p><strong>Table:</strong></p><p>Vacutainer tubes: Colours, anticoagulants and uses</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Spherocytosis in blood smear seen in-", "options": [{"label": "A", "text": "Mechanical trauma", "correct": false}, {"label": "B", "text": "Hereditary spherocytosis", "correct": false}, {"label": "C", "text": "Hemolytic disease of newborn", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Spherocytosis in blood smear seen in- Mechanical trauma, Hereditary spherocytosis & Hemolytic disease of newborn. Spherocytosis is seen in AIHA (Warm and cold) Acute and delayed hemolytic transfusion reactions ABO Rh hemolytic disease of newborn Hereditary spherocytosis Clostridium sepsis IV water infusion or drowning (fresh water) Hypophosphatemia Bartonellosis Snake bite Hyposplenism Rh-null phenotype Mechanical trauma Burns</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Mechanical trauma. Spherocytosis is seen . Option: B. Hereditary spherocytosis. Spherocytosis is seen . Option: C. Hemolytic disease of the newborn. Spherocytosis is seen .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Iron absorption is increased by:", "options": [{"label": "A", "text": "Phytates", "correct": false}, {"label": "B", "text": "Tannates", "correct": false}, {"label": "C", "text": "Plant food", "correct": false}, {"label": "D", "text": "Ascorbic acid", "correct": true}], "correct_answer": "D. Ascorbic acid", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ascorbic acid The bioavailability of dietary iron is as important as the overall content. The absorption of inorganic iron is influenced by other dietary contents. It is enhanced by ascorbic acid, citric acid, amino acids, and sugars in the diet , and it is inhibited by tannates (found in tea), carbonates, oxalates, and phosphates . Iron Absorption Site of iron absorption: duodenum and upper jejunum (proximal small intestine) Q . Ferrous form (Fe 2 +) of Iron is absorbed. Transport of Fe2+ into enterocyte occurs via DMT1 Q . Increased by Decreased by Acids Ascorbic acid (Vitamin C) Q Amino acid containing SH-group Meat (these reduce Phytates Fe 3 + to Fe 2 +) Alkalies PhosphatesQ Phytates Q Tetracycline Presence of other food in stomach</p>\n<p><strong>Highyeild:</strong></p><p>Iron transport: Regulation of iron absorption. Duodenal epithelial cell uptake of heme and nonheme iron is described in the text. When the storage sites of the body are replete with iron and erythropoietic activity is normal, plasma hepcidin balances iron uptake and loss to and maintains iron homeostasis by downregulating ferroportin and limiting iron uptake (middle panel). Hepcidin rises in the setting of systemic inflammation or when liver iron levels are high, decreasing iron uptake and increasing iron loss during the shedding of duodenocytes (right panel). Conversely, hepcidin levels fall in the setting of low plasma iron, primary hemochromatosis, or ineffective hematopoiesis (left panel), leading to a rise in iron absorption. DMTI, Divalent metal transporter I. Hepcidin: Iron absorption in the duodenum is regulated by hepcidin, a small circulating peptide that is synthesized and released from the liver in response to increases in intrahepatic iron levels. Hepcidin inhibits iron transfer from the enterocyte to plasma by binding to ferroportin , causing ferroportin to be endocytosed and degraded . As a result, as hepcidin levels rise , iron becomes trapped within duodenal cells in the form of mucosal ferritin and is lost as these cells slough . Ferroportin: It is a transmembrane protein that transports iron from the inside of a cell to the outside of the cell . Ferroportin is the only known iron exporter . Ferritin: The ferritin blood test measures how much iron is stored in a person’s body. Elevated ferritin concentration is considered a marker for high body iron stores .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Phytates. Decrease absorption of iron . Option: B. Tannates. Decrease absorption of iron . Option: C. Plant food. Decrease absorption of iron .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 30 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Based on the classification of RPGN with its etiological factor. Identify the wrong match:", "options": [{"label": "A", "text": "Type I - Goodpasture syndrome", "correct": false}, {"label": "B", "text": "TypeII - IgA nephropathy", "correct": false}, {"label": "C", "text": "Type II - Henoch-Schönlein purpura", "correct": false}, {"label": "D", "text": "Type III - Lupus nephritis", "correct": true}], "correct_answer": "D. Type III - Lupus nephritis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Type III - Lupus nephritis Type III RPGN is typically associated with pauci-immune glomerulonephritis and is commonly seen in patients with small-vessel vasculitis, such as granulomatosis with polyangiitis (formerly known as Wegener's granulomatosis) and microscopic polyangiitis.</p>\n<p><strong>Highyeild:</strong></p><p>Rapidly progressive glomerulonephritis Aka Crescentic glomerulonephritis RPGN is characterized by the formation of crescent -shaped structures in the glomeruli, which are made up of fibrin, immune cells, proliferating parietal cells , and other components. It is characterized by loss of kidney function over a short period of time. Urinalysis shows hematuria and proteinuria. RPGN is classified into three types based on the etiology: Type I (anti-GBM antibody-mediated), Type II (immune complex-mediated), and Type III (pauci-immune).</p>\n<p><strong>Table:</strong></p><p>Rapid Progressive Glomerulonephritis: 3 classes Type 1 RPGN Type 2 RPGN Type 3 RPGN Anti-GBM antibody associated Immune complex - mediated Pauci-immune IF: Linear deposition of IgG along the glomerular basement membrane IF: Granular deposition of IgG, IgM, and/or C3 in\n glomeruli IF: No significant deposition of immunoglobulins\n or complement Goodpasture syndrome Idiopathic Postinfectious glomerulonephritis Lupus nephritis Henoch-Schönlein purpura IgA nephropathy Others ANCA-associated Idiopathic Granulomatosis with polyangiitis (formerly Wegener granulomatosis)\n Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which class of rapidly Progressive (Crescentic) Glomerulonephritis is associated with the presence of ANCA?", "options": [{"label": "A", "text": "Type I (Anti-GBM Antibody)", "correct": false}, {"label": "B", "text": "Type II (Immune Complex)", "correct": false}, {"label": "C", "text": "Type III (Pauci-Immune)", "correct": true}, {"label": "D", "text": "All of the above", "correct": false}], "correct_answer": "C. Type III (Pauci-Immune)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Type III (Pauci-Immune) The class of rapidly Progressive (Crescentic) Glomerulonephritis that is associated with the presence of ANCA is Type III (Pauci-Immune). ANCA is a marker for the presence of small vessel vasculitis (Wegener’s granulomatosis: C-ANCA and microscopic polyangiitis: P-ANCA) and is commonly seen in pauci-immune crescentic glomerulonephritis, which is characterized by the absence of immune complexes.</p>\n<p><strong>Highyeild:</strong></p><p>Rapidly progressive glomerulonephritis Aka Crescentic glomerulonephritis RPGN is characterized by the formation of crescent -shaped structures in the glomeruli, which are made up of fibrin, immune cells, proliferating parietal cells , and other components. It is characterized by loss of kidney function over a short period of time. Urinalysis shows hematuria and proteinuria. RPGN is classified into three types based on the etiology: Type I (anti-GBM antibody-mediated), Type II (immune complex-mediated), and Type III (pauci-immune).</p>\n<p><strong>Table:</strong></p><p>Rapid Progressive Glomerulonephritis: 3 classes Type 1 RPGN Type 2 RPGN Type 3 RPGN Anti-GBM antibody associated Immune complex - mediated Pauci-immune IF: Linear deposition of IgG along the glomerular basement membrane IF: Granular deposition of IgG, IgM, and/or C3 in glomeruli IF: No significant deposition of immunoglobulins or complement Goodpasture syndrome Idiopathic Postinfectious glomerulonephritis Lupus nephritis Henoch-Schönlein purpura IgA nephropathy Others ANCA-associated Idiopathic Granulomatosis with polyangiitis (formerly Wegener granulomatosis) Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are constituents of the crescent except:", "options": [{"label": "A", "text": "Parietal cells", "correct": false}, {"label": "B", "text": "Fibrin", "correct": false}, {"label": "C", "text": "Monocytes", "correct": false}, {"label": "D", "text": "Mesangial cells", "correct": true}], "correct_answer": "D. Mesangial cells", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mesangial cells Mesangial cell s are not a constituent of crescents. Crescents are cellular deposits that are composed of proliferating parietal cells, infiltrating monocytes or macrophages, and fibrin . The crescents may obliterate the urinary space and compress the glomerular tuft.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Rapidly Progressive (Crescentic) Glomerulonephritis with pauci-immune status is associated with:", "options": [{"label": "A", "text": "Good pasture syndrome", "correct": false}, {"label": "B", "text": "Postinfectious glomerulonephritis", "correct": false}, {"label": "C", "text": "Wegener granulomatosis", "correct": true}, {"label": "D", "text": "IgA nephropathy", "correct": false}], "correct_answer": "C. Wegener granulomatosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Wegener granulomatosis Pauci immune type of RPGN may be a component of systemic vasculitis such as granulomatosis with polyangiitis -formerly called Wegener granulomatosis or microscopic polyangiitis.</p>\n<p><strong>Highyeild:</strong></p><p>Rapidly progressive glomerulonephritis Aka Crescentic glomerulonephritis RPGN is characterized by the formation of crescent -shaped structures in the glomeruli, which are made up of fibrin, immune cells, proliferating parietal cells , and other components. It is characterized by loss of kidney function over a short period of time. Urinalysis shows hematuria and proteinuria. RPGN is classified into three types based on the etiology: Type I (anti-GBM antibody-mediated), Type II (immune complex-mediated), and Type III (pauci-immune).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Goodpasture syndrome: It is characterized by the presence of anti-glomerular basement membrane antibodies. It is responsible for type 1 RPGN. Option: B. Postinfectious glomerulonephritis: This type of glomerulonephritis is associated with a history of recent streptococcal infection and typically shows immune complex deposition on immunofluorescence. It is not pauci-immune. Option: D. IgA nephropathy: This type of glomerulonephritis is characterized by IgA immune complex deposition, typically in the mesangium. It is not typically associated with a pauci-immune status.</p>\n<p><strong>Table:</strong></p><p>Rapid Progressive Glomerulonephritis: 3 classes Type 1 RPGN Type 2 RPGN Type 3 RPGN Anti-GBM antibody associated Immune complex - mediated Pauci-immune IF: Linear deposition of IgG along the glomerular basement membrane IF: Granular deposition of IgG, IgM, and/or C3 in glomeruli IF: No significant deposition of immunoglobulins or complement Goodpasture syndrome Idiopathic Postinfectious glomerulonephritis Lupus nephritis Henoch-Schönlein purpura IgA nephropathy Others ANCA-associated Idiopathic Granulomatosis with polyangiitis (formerly Wegener granulomatosis) Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 26-year-old patient presented with proteinuria, and hematuria. The PAS stain of renal biopsy is shown below. What is the likely diagnosis?", "options": [{"label": "A", "text": "Postinfectious streptococcal glomerulonephritis", "correct": false}, {"label": "B", "text": "Rapidly progressive glomerulonephritis", "correct": true}, {"label": "C", "text": "Membranous nephropathy", "correct": false}, {"label": "D", "text": "Mesangio proliferative glomerulonephritis", "correct": false}], "correct_answer": "B. Rapidly progressive glomerulonephritis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Rapidly progressive glomerulonephritis The given clinical scenario with a histological picture showing crescents is suggestive of Rapidly progressive glomerulonephritis (RPGN). RPGN is a type of glomerulonephritis characterized by rapid deterioration of renal function, usually resulting in acute kidney injury. The presence of crescents on renal biopsy is a hallmark feature of RPGN.</p>\n<p><strong>Highyeild:</strong></p><p>Rapidly progressive glomerulonephritis Aka Crescentic glomerulonephritis RPGN is characterized by the formation of crescent -shaped structures in the glomeruli, which are made up of fibrin, immune cells, proliferating parietal cells , and other components. It is characterized by loss of kidney function over a short period of time. Urinalysis shows hematuria and proteinuria. RPGN is classified into three types based on the etiology: Type I (anti-GBM antibody-mediated), Type II (immune complex-mediated), and Type III (pauci-immune).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Post Infectious streptococcal glomerulonephritis: It typically presents with a history of recent streptococcal infection and is characterized by diffuse proliferative glomerulonephritis without crescents. Option: C. Membranous nephropathy: It is characterized by diffuse thickening of the glomerular basement membrane and the presence of immune complex deposits. Option: D. Mesangio proliferative glomerulonephritis: It is characterized by mesangial cell proliferation and thickening of the mesangial matrix without crescents.</p>\n<p><strong>Extraedge:</strong></p><p>Types of Glomerulonephritis Glomerular Deposits IgA Nephropathy Mesangial Membranous Nephropathy Subepithelial Membranoproliferative GN Subendothelial Poststreptococcal GN Subepithelial humps Rapidly Progressive GN Crescents Lupus Nephritis Subendothelial Cryoglobulinemic GN Subendothelial</p>\n<p><strong>Table:</strong></p><p>Rapid Progressive Glomerulonephritis: 3 classes Type 1 RPGN Type 2 RPGN Type 3 RPGN Anti-GBM antibody associated Immune complex - mediated Pauci-immune IF: Linear deposition of IgG along the glomerular basement membrane IF: Granular deposition of IgG, IgM, and/or C3 in glomeruli IF: No significant deposition of immunoglobulins or complement Goodpasture syndrome Idiopathic Postinfectious glomerulonephritis Lupus nephritis Henoch-Schönlein purpura IgA nephropathy Others ANCA-associated Idiopathic Granulomatosis with polyangiitis (formerly Wegener granulomatosis) Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding angiogenesis except:", "options": [{"label": "A", "text": "VEGF stimulates both the migration and proliferation of endothelial cells", "correct": false}, {"label": "B", "text": "Angiopoietin 1&2 plays a role in angiogenesis and structural maturation of new vessels", "correct": false}, {"label": "C", "text": "PDGF recruits smooth muscle cells", "correct": false}, {"label": "D", "text": "TGF- β causes endothelial proliferation and migration along with suppression of ECM protein", "correct": true}], "correct_answer": "D. TGF- β causes endothelial proliferation and migration along with suppression of ECM protein", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TGF- β causes endothelial proliferation and migration along with suppression of ECM protein Angiogenesis is the process of new blood vessel development from existing vessels . It is critical in healing at sites of injury , in the development of collateral circulations at sites of ischemia , and in allowing tumours to increase in size beyond the constraints of their original blood supply. Vascular endothelial growth factors (VEGFs), mainly VEGF-A , stimulate both migration and proliferation of endothelial cells , thus initiating the process of capillary sprouting in angiogenesis. Angiopoietins 1 and 2 (Ang 1 and Ang 2) are growth factors that play a role in angiogenesis and the structural maturation of new vessels . The growth factors PDGF and TGF-β also participate in stabilisation: PDGF recruits smooth muscle cells, and TGF-β suppresses endothelial proliferation and migration and enhances the production of ECM proteins .</p>\n<p><strong>Highyeild:</strong></p><p>Angiogenesis in tumor cells: Even if a solid tumor possesses all the genetic aberrations required for malignant transformation, it cannot enlarge beyond 1 to 2 mm in diameter unless it can induce angiogenesis . Angiogenesis is controlled by a balance between angiogenesis promoters and inhibitors ; in angiogenic tumors this balance is skewed in favor of promoters. Hypoxia triggers angiogenesis through the actions of HIF1α on the transcription of the pro-angiogenic factor VEGF . Many other factors regulate angiogenesis, e.g., p53 induces synthesis of the angiogenesis inhibitor thrombospondin-1 , while RAS, MYC, and MAPK signalling all upregulate VEGF expression and stimulate angiogenesis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. VEGF stimulates both migration and proliferation of endothelial cells. True . Option: B. Angiopoietin 1&2 play your role in angiogenesis and structural maturation of new vessels. True . Option: C. PDGF recruits smooth muscle cells. True .</p>\n<p><strong>Extraedge:</strong></p><p>The idea that angiogenesis is essential for solid tumors to grow to clinically significant sizes has helped develop new treatment modalities against cancer. A cardinal example is bevacizumab , a monoclonal antibody that neutralises VEGF activity and is approved for treating multiple cancers but is not curative .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the mentioned growth factors predominantly orchestrate deposition of connective tissue except", "options": [{"label": "A", "text": "PGDF", "correct": false}, {"label": "B", "text": "FGF 2", "correct": false}, {"label": "C", "text": "TGF beta", "correct": false}, {"label": "D", "text": "TNF", "correct": true}], "correct_answer": "D. TNF", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TNF TNF is an inflammatory mediator , a cytokine with local (endothelial activation) and systemic effects (fever, hypotension, DIC, etc.) The laying down of connective tissue occurs in two steps: Migration and proliferation of fibroblasts into the site of injury. Deposition of ExtraCellular Matrix (ECM) proteins produced by these cells. These processes are orchestrated by locally produced cytokines and growth factors, including PDGF , FGF-2 , and TGF-β . The primary sources of these factors are inflammatory cells, particularly alternatively activated (M2) macrophages , present at sites of injury and in granulation tissue.</p>\n<p><strong>Highyeild:</strong></p><p>Anti-inflammatory mediators are: Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. PGDF. It plays a role in laying down connective tissue. Option: B. FGF 2. It plays a role in laying down connective tissue. Option: C. TGF beta. It plays a role in laying down connective tissue.</p>\n<p><strong>Extraedge:</strong></p><p>Classical and alternative macrophage activation. Different stimuli activate monocytes/macrophages to develop into functionally distinct populations. Classically activated macrophages are induced by microbial products and cytokines, particularly interferon-y (IFN-y). They phagocytose and destroy microbes and dead tissues and can potentiate inflammatory reactions. Alternatively activated macrophages are induced by other cytokines and are important in tissue repair and resolution of inflammation. IL, Interleukin; NO, nitric oxide; ROS, reactive oxygen species; TGF-B, transforming growth factor-B; TLR, Toll-like receptor.</p>\n<p><strong>Table:</strong></p><p>mediators : Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by\n inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the function of TGF beta, except:", "options": [{"label": "A", "text": "It stimulates fibroblast proliferation and migration", "correct": false}, {"label": "B", "text": "Increases synthesis of collagen and fibronectin", "correct": false}, {"label": "C", "text": "Increases the action of matrix metalloproteinases", "correct": true}, {"label": "D", "text": "Involved in scar formation", "correct": false}], "correct_answer": "C. Increases the action of matrix metalloproteinases", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increases the action of matrix metalloproteinases The primary sources of TGF-β are inflammatory cells, particularly alternatively activated (M2) macrophages , present at sites of injury and in granulation tissue. TGF-β causes: Stimulation of fibroblast migration and proliferation Increase in the synthesis of collagen and fibronectin Decrease in degradation of ECM due to inhibition of metalloproteinases . TGF-β is involved in scar formation after injury and in the development of fibrosis in the lungs, liver, and kidneys that follows chronic inflammation .</p>\n<p><strong>Highyeild:</strong></p><p>Anti-inflammatory mediators are: Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It stimulates fibroblast proliferation and migration. True . Option: B. Increases synthesis of collagen and fibronectin. True . Option: D. Involved in scar formation. True .</p>\n<p><strong>Extraedge:</strong></p><p>Classical and alternative macrophage activation. Different stimuli activate monocytes/macrophages to develop into functionally distinct populations. Classically activated macrophages are induced by microbial products and cytokines, particularly interferon-y (IFN-y). They phagocytose and destroy microbes and dead tissues and can potentiate inflammatory reactions. Alternatively activated macrophages are induced by other cytokines and are important in tissue repair and resolution of inflammation. IL, Interleukin; NO, nitric oxide; ROS, reactive oxygen species; TGF-B, transforming growth factor-B; TLR, Toll-like receptor.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which growth factor is involved in lung, liver and kidney fibrosis after chronic inflammation?", "options": [{"label": "A", "text": "IL 1", "correct": false}, {"label": "B", "text": "FGF 2", "correct": false}, {"label": "C", "text": "TGF beta", "correct": true}, {"label": "D", "text": "TNF", "correct": false}], "correct_answer": "C. TGF beta", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>TGF beta The primary sources of TGF-β are inflammatory cells, particularly alternatively activated (M2) macrophages , present at injury sites and in granulation tissue. TGF-β causes: Stimulation of fibroblast migration and proliferation Increase in the synthesis of collagen and fibronectin Decrease in degradation of ECM due to inhibition of metalloproteinases . TGF-β is involved in scar formation after injury and in the development of fibrosis in lungs, liver, and kidneys that follows chronic inflammation .</p>\n<p><strong>Highyeild:</strong></p><p>Anti-inflammatory mediators are: Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. IL 1. An inflammatory mediator causes fever . Option: B. FGF 2. It plays a role in laying down connective tissue . Option: D. TNF. An inflammatory mediator causes fever .</p>\n<p><strong>Extraedge:</strong></p><p>Classical and alternative macrophage activation. Different stimuli activate monocytes/macrophages to develop into functionally distinct populations. Classically activated macrophages are induced by microbial products and cytokines, particularly interferon-y (IFN-y). They phagocytose and destroy microbes and dead tissues and can potentiate inflammatory reactions. Alternatively activated macrophages are induced by other cytokines and are important in tissue repair and resolution of inflammation. IL, Interleukin; NO, nitric oxide; ROS, reactive oxygen species; TGF-B, transforming growth factor-B; TLR, Toll-like receptor.</p>\n<p><strong>Table:</strong></p><p>mediators : Interleukin- 10 (IL- 4, IL- 13) Lipoxins ( LXA4 , LXB4 ) - The lipoxins suppress inflammation by\n inhibiting neutrophil chemotaxis and adhesion to endothelium. TGF- β - It helps in tissue healing .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following promotes migration of fibroblast to wound area in case of angiogenesis process of wound healing?", "options": [{"label": "A", "text": "EGF", "correct": false}, {"label": "B", "text": "PDGF", "correct": false}, {"label": "C", "text": "VEGF", "correct": false}, {"label": "D", "text": "FGF", "correct": true}], "correct_answer": "D. FGF", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>FGF Fibroblast growth factors (FGFs), mainly FGF-2 , stimulate the proliferation of endothelial cells . It also promotes the migration of macrophages and fibroblasts to the damaged area and stimulates epithelial cell migration to cover epidermal wounds .</p>\n<p><strong>Highyeild:</strong></p><p>Growth Factors Involved in Regeneration and Repair Growth Factor Sources Functions Epidermal growth factor (EGF) Activated macrophages, salivary glands, keratinocytes, many other cells Mitogenic for many cell types; stimulates epithelial cell migration; stimulates formation of granulation tissue Transforming growth factor-α (TGF-α) Activated macrophages, keratinocytes, many other cells Stimulates proliferation of hepatocytes and many other epithelial cells Hepatocyte growth factor (HGF) (scatter factor) Fibroblasts, stromal cells in the liver, endothelial cells Enhances proliferation of hepatocytes and other epithelial cells; increases cell motility Vascular endothelial growth factor (VEGF Mesenchymal cells Stimulates proliferation of endothelial cells; increases vascular permeability Platelet-derived growth factor (PDGF) Platelets, macrophages, endothelial cells, smooth muscle cells, keratinocytes Chemotactic for neutrophils, macrophages, fibroblasts, and smooth muscle cells; activates and stimulates proliferation of fibroblasts, endothelial cells, and other cells; stimulates ECM protein synthesis Fibroblast growth factors (FGF s ) including acidic (FGF-1) and basic (FGF-2) Macrophages, mast cells, endothelial cells, many other cell types Chemotactic and mitogenic for fibroblasts; stimulates angiogenesis and ECM protein synthesis Transforming growth factor-β(TGF-β) Platelets, T lymphocytes, macrophages, endothelial cells, epithelial cells, smooth muscle cells, fibroblasts Chemotactic for leukocytes and fibroblasts; stimulates ECM protein synthesis; suppresses acute inflammation Keratinocyte growth factor (KGF) (i.e., FGF-7) Fibroblasts Stimulates keratinocyte migration, proliferation, and differentiation</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. EGF. The epidermal Growth Factor is involved in the regulation of cell proliferation . Option: B. PDGF. Platelet-Derived Growth Factor helps heal wounds and repair damage to blood vessel walls Option: C. VEGF. Vascular endothelial growth factor (VEGF) is considered the master regulator of angiogenesis during growth and development , as well as in disease states such as cancer , diabetes , and macular degeneration .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which cell contributes to the contraction of scar?", "options": [{"label": "A", "text": "Myofibroblast", "correct": true}, {"label": "B", "text": "Fibroblast", "correct": false}, {"label": "C", "text": "Epithelial cell", "correct": false}, {"label": "D", "text": "Collagen", "correct": false}], "correct_answer": "A. Myofibroblast", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myofibroblast As the scar matures , there is progressive vascular regression , which eventually transforms the highly vascularised granulation tissue into a pale, largely avascular scar . Some of the fibroblasts also acquire features of smooth muscle cells , including the presence of actin filaments, and are called myofibroblasts . These cells contribute to the contraction of the scar over time.</p>\n<p><strong>Highyeild:</strong></p><p>Wound contraction helps close the wound by decreasing the gap between its dermal edges and reducing the wound surface area. Hence it is an important feature in healing by the secondary union . Wound contraction involves forming a network of myofibroblasts, which are modified fibroblasts with contractile properties .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Fibroblast. Results in fibrosis , but the contraction of the wound is because of specialised Fibroblasts called Myofibroblasts. Option: C. Epithelial cell. Do not cause contraction of the scar. Option: D. Collagen. Do not cause contraction of the scar.</p>\n<p><strong>Extraedge:</strong></p><p>Excessive scarring: Excessive formation of the components of the repair process can give rise to hypertrophic scars and keloids . These often grow rapidly and contain abundant myofibroblasts , but they tend to regress over several months ( Hypertrophic scar ) or do not regress ( Keloid ).</p>\n<p><strong>Table:</strong></p><p>Hypertrophic scar vs Keloid</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The ultra-structural finding has been given below. Identify the change:", "options": [{"label": "A", "text": "Reversible injury", "correct": true}, {"label": "B", "text": "Irreversible injury", "correct": false}, {"label": "C", "text": "Necrosis", "correct": false}, {"label": "D", "text": "Apoptosis", "correct": false}], "correct_answer": "A. Reversible injury", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686812223874-QTDP006001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reversible injury Cellular swelling is the first manifestation of almost all forms of injury to cells. It is a difficult morphologic change to appreciate with the light microscope; it may be more apparent at the level of the whole organ. When it affects many cells , it causes some pallor, increased turgor, and an increase in the weight of the organ . On microscopic examination , small clear vacuoles may be seen within the cytoplasm ; these represent distended and pinched-off segments of the ER . This pattern of nonlethal injury is sometimes called hydropic change or vacuolar degeneration . The swelling of cells is reversible. Cells may also show increased eosinophilic staining , which becomes much more pronounced with progression to necrosis . Epithelial cells of the proximal tubule showing early cell injury resulting from reperfusion following ischemia. The microvilli are lost and have been incorporated in apical cytoplasm; blebs have formed and are extruded in the lumen. Mitochondria (M) would have been swollen during ischemia; with reperfusion, they rapidly undergo condensation and become electron-dense</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with the detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements</p>\n<p><strong>Extraedge:</strong></p><p>Nuclear change s appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. Over time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following is not a reversible cell injury finding:", "options": [{"label": "A", "text": "Loss of microvilli in the plasma membrane", "correct": false}, {"label": "B", "text": "Lipid vacuoles in the cytoplasm", "correct": false}, {"label": "C", "text": "Amorphous densities", "correct": true}, {"label": "D", "text": "Cytoplasmic vacuoles", "correct": false}], "correct_answer": "C. Amorphous densities", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Amorphous densities On microscopic examination , small clear vacuoles may be seen within the cytoplasm ; these represent distended and pinched-off segments of the ER . This pattern of nonlethal injury is sometimes called hydropic change or vacuolar degeneration . The swelling of cells is reversible. Cells may also show increased eosinophilic staining , which becomes much more pronounced with progression to necrosis .</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with the detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Loss of microvilli in the plasma membrane. Seen in reversible cell injury . Option: B. Lipid vacuoles in the cytoplasm. Seen in reversible cell injury . Option: D. Cytoplasmic vacuoles. Seen in reversible cell injury .</p>\n<p><strong>Extraedge:</strong></p><p>Nuclear change s appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. With the passage of time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding reversible cell injury except?", "options": [{"label": "A", "text": "Formation of amorphous densities in the Mitochondrial matrix", "correct": true}, {"label": "B", "text": "Diminished generation of adenosine triphosphate (ATP)", "correct": false}, {"label": "C", "text": "Formation of blebs in the plasma membrane", "correct": false}, {"label": "D", "text": "Detachment of ribosomes from the granular Endoplasmic reticulum", "correct": false}], "correct_answer": "A. Formation of amorphous densities in the Mitochondrial matrix", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Formation of amorphous densities in the Mitochondrial matrix The formation of large amorphous densities in mitochondria and Myelin figures in the cytoplasm are features of irreversible cell injury seen under the electron microscope.</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with the detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements Nuclear change s appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. Over time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Diminished generation of adenosine triphosphate (ATP). Diminished generation of ATP is seen in both reversible and irreversible cell injuries . Option: C. Formation of blebs in the plasma membrane. Seen in reversible cell injury . Option: D. Detachment of ribosomes from the granular Endoplasmic reticulum. Seen in reversible cell injury .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are reversible pathological changes except:", "options": [{"label": "A", "text": "Hydropic swelling", "correct": false}, {"label": "B", "text": "Fatty change", "correct": false}, {"label": "C", "text": "Visible vacuoles in the cytoplasm", "correct": false}, {"label": "D", "text": "Karyorrhexis", "correct": true}], "correct_answer": "D. Karyorrhexis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Karyorrhexis Nuclear changes are seen in irreversible cell injury and appear in one of three patterns, all due to the breakdown of DNA: The basophilia of the chromatin may fade Karyolysis Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation.</p>\n<p><strong>Highyeild:</strong></p><p>The ultrastructural changes of reversible cell injury, visible by electron microscopy, include the following: Plasma membrane alterations, such as blebbing , blunting, and loss of microvilli Mitochondrial changes, including swelling and the appearance of small amorphous densities Accumulation of “ myelin figures ” in the cytosol composed of phospholipids derived from damaged cellular membranes Dilation of the ER, with the detachment of polysomes Nuclear alterations , with disaggregation of granular and fibrillar elements Nuclear change s appear in one of three patterns : The basophilia of the chromatin may fade Karyolysis Pyknosis is characterised by nuclear shrinkage and increased basophilia. Karyorrhexis , the pyknotic nucleus undergoes fragmentation. With time (a day or two), the nucleus in the necrotic cell totally disappears.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hydropic swelling. Generalized swelling of the cell and its organelles, blebbing of the plasma membrane. The swelling of cells results from an influx of water . Caused by failure of the ATP-dependent Na-K plasma membrane pump due to depletion of ATP, which causes Na to accumulate inside the cell, which pulls water into the cell causing swelling. Option: B. Fatty change. Fatty change occurs in organs that are actively involved in lipid metabolism (e.g., the liver) . It results when a toxic injury disrupts metabolic pathways and leads to rapid accumulation of triglyceride-filled lipid vacuoles . Option: C. Visible vacuoles in the cytoplasm. On microscopic examination, small clear vacuoles may be seen within the cytoplasm ; these represent distended and pinched-off segments of the ER . This pattern of nonlethal injury is sometimes called hydropic change or vacuolar degeneration .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Aschoff bodies consist of all of the following except:", "options": [{"label": "A", "text": "T lymphocytes", "correct": false}, {"label": "B", "text": "Plasma cell", "correct": false}, {"label": "C", "text": "B lymphocytes", "correct": true}, {"label": "D", "text": "Activated macrophages", "correct": false}], "correct_answer": "C. B lymphocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B lymphocytes Aschoff bodies —are composed of foci of T lymphocytes , occasional plasma cells , and plump activated macrophages called Anitschkow cells .</p>\n<p><strong>Highyeild:</strong></p><p>Rheumatic Heart Disease: Acute immunologically mediated multisystem inflammatory disease due to Group A β Hemolytic Streptococci . Starts at 7-21 days after pharyngitis . Age commonly affected: 5- 10 years Type 2 Hypersensitivity reaction Distinctive lesions in the heart—called Aschoff bodies —are composed of foci of T lymphocytes, occasional plasma cells , and plump activated macrophages called Anitschkow cells . These macrophages have abundant cytoplasm and central round-to-ovoid nuclei (occasionally binucleate) in which the chromatin condenses into a central, slender, wavy ribbon (hence the designation “ caterpillar cells ”). During acute Rheumatic Fever (RF), diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ). Inflammation of the endocardium and the left-sided valves typically results in fibrinoid necrosis within the cusps or tendinous cords. Overlying these necrotic foci and along the lines of closure are small (1 to 2 mm) vegetations, called verrucae . Subendocardial lesions, perhaps exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium . The cardinal anatomic changes of the mitral valve in chronic RHD are leaflet thickening , commissural fusion and shortening , and thickening and fusion of the tendinous cords . The mitral valve is virtually always involved in chronic RHD ; it is affected in isolation in roughly two-thirds of cases, and along with the aortic valve in another 25%. Tricuspid valve involvement is infrequent, and the pulmonary valve is only rarely affected . In rheumatic mitral stenosis, calcification and fibrous bridging across the valvular commissures create “ fish mouth ” stenoses . With tight mitral stenosis, the left atrium progressively dilates and may harbor mural thrombi that can embolize . Long-standing congestive changes in the lungs may induce pulmonary vascular and parenchymal changes; over time, these can lead to right ventricular hypertrophy . The left ventricle is largely unaffected by isolated pure mitral stenosis . Microscopically, valves show the organization of the acute inflammation , with postinflammatory neovascularization and transmural fibrosis that obliterate the leaflet architecture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. T lymphocytes. Correct . Option: B. Plasma cell. Correct . Option: D. Activated macrophages. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Secondary Prophylaxis for patients with RHD: Category Dusation prophylacil 1. Rheumatic fever (without carditis · 5 year after last attack Or · 21 years of age (whichever is longer) 2. Rheumatic fever carditis (without residual valve disease) · 10year after last attack Or · 21 years of age (whichever is longer) 3. Rheumatic fever with persistent Valvular disease (clinical or echo based) · 10year after last attack Or · 21 years of age (whichever is longer)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statement are true regarding activated macrophages in Aschoff bodies?", "options": [{"label": "A", "text": "Pathognomonic for RF", "correct": false}, {"label": "B", "text": "Called a caterpillar cell", "correct": false}, {"label": "C", "text": "Also known as Anitschkow cells", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above</p>\n<p><strong>Highyeild:</strong></p><p>Rheumatic Heart Disease: Acute immunologically mediated multisystem inflammatory disease due to Group A β Hemolytic Streptococci . Starts at 7-21 days after pharyngitis . Age commonly affected: 5- 10 years Type 2 Hypersensitivity reaction Distinctive lesions in the heart—called Aschoff bodies —are composed of foci of T lymphocytes, occasional plasma cells , and plump activated macrophages called Anitschkow cells . These macrophages have abundant cytoplasm and central round-to-ovoid nuclei (occasionally binucleate) in which the chromatin condenses into a central, slender, wavy ribbon (hence the designation “ caterpillar cells ”). During acute Rheumatic Fever (RF), diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ). Inflammation of the endocardium and the left-sided valves typically results in fibrinoid necrosis within the cusps or tendinous cords. Overlying these necrotic foci and along the lines of closure are small (1 to 2 mm) vegetations, called verrucae . Subendocardial lesions, perhaps exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium . The cardinal anatomic changes of the mitral valve in chronic RHD are leaflet thickening , commissural fusion and shortening , and thickening and fusion of the tendinous cords . The mitral valve is virtually always involved in chronic RHD ; it is affected in isolation in roughly two-thirds of cases, and along with the aortic valve in another 25%. Tricuspid valve involvement is infrequent, and the pulmonary valve is only rarely affected . In rheumatic mitral stenosis, calcification and fibrous bridging across the valvular commissures create “ fish mouth ” stenoses . With tight mitral stenosis, the left atrium progressively dilates and may harbor mural thrombi that can embolize . Long-standing congestive changes in the lungs may induce pulmonary vascular and parenchymal changes; over time, these can lead to right ventricular hypertrophy . The left ventricle is largely unaffected by isolated pure mitral stenosis . Microscopically, valves show the organization of the acute inflammation , with postinflammatory neovascularization and transmural fibrosis that obliterate the leaflet architecture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Pathognomonic for RF. Correct . Option: B. Called a caterpillar cell. Correct . Option: C. Also known as Anitschkow cells. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Secondary Prophylaxis for patients with RHD: Category Dusation prophylacil 1. Rheumatic fever (without carditis · 5 year after last attack Or · 21 years of age (whichever is longer) 2. Rheumatic fever carditis (without residual valve disease) · 10year after last attack Or · 21 years of age (whichever is longer) 3. Rheumatic fever with persistent Valvular disease (clinical or echo based) · 10year after last attack Or · 21 years of age (whichever is longer)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding histological features of rheumatic heart disease except:", "options": [{"label": "A", "text": "Diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart", "correct": false}, {"label": "B", "text": "Subendocardial lesions, McCallum plaques, are usually found in the right atrium", "correct": true}, {"label": "C", "text": "Leaflet thickening and commissural fusion are seen", "correct": false}, {"label": "D", "text": "Shortening, thickening, and fusion of the tendinous cords are seen", "correct": false}], "correct_answer": "B. Subendocardial lesions, McCallum plaques, are usually found in the right atrium", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Subendocardial lesions, McCallum plaques, are usually found in the right atrium False , subendocardial lesions, exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium .</p>\n<p><strong>Highyeild:</strong></p><p>Rheumatic Heart Disease: Acute immunologically mediated multisystem inflammatory disease due to Group A β Hemolytic Streptococci . Starts at 7-21 days after pharyngitis . Age commonly affected: 5- 10 years Type 2 Hypersensitivity reaction Distinctive lesions in the heart—called Aschoff bodies —are composed of foci of T lymphocytes, occasional plasma cells , and plump activated macrophages called Anitschkow cells . These macrophages have abundant cytoplasm and central round-to-ovoid nuclei (occasionally binucleate) in which the chromatin condenses into a central, slender, wavy ribbon (hence the designation “ caterpillar cells ”). During acute Rheumatic Fever (RF), diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ). Inflammation of the endocardium and the left-sided valves typically results in fibrinoid necrosis within the cusps or tendinous cords. Overlying these necrotic foci and along the lines of closure are small (1 to 2 mm) vegetations, called verrucae . Subendocardial lesions, perhaps exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium . The cardinal anatomic changes of the mitral valve in chronic RHD are leaflet thickening , commissural fusion and shortening , and thickening and fusion of the tendinous cords . The mitral valve is virtually always involved in chronic RHD ; it is affected in isolation in roughly two-thirds of cases, and along with the aortic valve in another 25%. Tricuspid valve involvement is infrequent, and the pulmonary valve is only rarely affected In rheumatic mitral stenosis, calcification and fibrous bridging across the valvular commissures create “ fish mouth ” stenoses . With tight mitral stenosis, the left atrium progressively dilates and may harbor mural thrombi that can embolize . Long-standing congestive changes in the lungs may induce pulmonary vascular and parenchymal changes; over time, these can lead to right ventricular hypertrophy . The left ventricle is largely unaffected by isolated pure mitral stenosis . Microscopically, valves show the organization of the acute inflammation , with postinflammatory neovascularization and transmural fibrosis that obliterate the leaflet architecture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart. Correct . Option: C. Leaflet thickening and commissural fusion is seen. Correct . Option: D. Shortening, thickening, and fusion of the tendinous cords are seen. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Secondary Prophylaxis for patients with RHD: Category Dusation prophylacil 1. Rheumatic fever (without carditis · 5 year after last attack Or · 21 years of age (whichever is longer) 2. Rheumatic fever carditis (without residual valve disease) · 10year after last attack Or · 21 years of age (whichever is longer) 3. Rheumatic fever with persistent Valvular disease (clinical or echo based) · 10year after last attack Or · 21 years of age (whichever is longer)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding rheumatic mitral stenosis except:", "options": [{"label": "A", "text": "Fishmouth or buttonhole deformity is seen", "correct": false}, {"label": "B", "text": "Left atrium progressively dilates and harbors mural thrombi", "correct": false}, {"label": "C", "text": "Acute inflammation, with post-inflammatory neovascularization and transmural fibrosis obliterates the leaflet", "correct": false}, {"label": "D", "text": "Vegetations are seen on either or both sides of the valve leaflets", "correct": true}], "correct_answer": "D. Vegetations are seen on either or both sides of the valve leaflets", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Vegetations are seen on either or both sides of the valve leaflets False , Rheumatic fever phase of rheumatic heart disease (RHD) is marked by small, warty vegetations along the lines of closure of the valve leaflets . Libman-Sacks endocarditis (LSE) has small- or medium-sized vegetation on either or both sides of the valve leaflets .</p>\n<p><strong>Highyeild:</strong></p><p>Rheumatic Heart Disease: Acute immunologically mediated multisystem inflammatory disease due to Group A β Hemolytic Streptococci . Starts at 7-21 days after pharyngitis . Age commonly affected: 5- 10 years Type 2 Hypersensitivity reaction Distinctive lesions in the heart—called Aschoff bodies —are composed of foci of T lymphocytes, occasional plasma cells , and plump activated macrophages called Anitschkow cells . These macrophages have abundant cytoplasm and central round-to-ovoid nuclei (occasionally binucleate) in which the chromatin condenses into a central, slender, wavy ribbon (hence the designation “ caterpillar cells ”). During acute Rheumatic Fever (RF), diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ). Inflammation of the endocardium and the left-sided valves typically results in fibrinoid necrosis within the cusps or tendinous cords. Overlying these necrotic foci and along the lines of closure are small (1 to 2 mm) vegetations, called verrucae . Subendocardial lesions, perhaps exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium . The cardinal anatomic changes of the mitral valve in chronic RHD are leaflet thickening , commissural fusion and shortening , and thickening and fusion of the tendinous cords . The mitral valve is virtually always involved in chronic RHD ; it is affected in isolation in roughly two-thirds of cases, and along with the aortic valve in another 25%. Tricuspid valve involvement is infrequent, and the pulmonary valve is only rarely affected In rheumatic mitral stenosis, calcification and fibrous bridging across the valvular commissures create “ fish mouth ” stenoses . With tight mitral stenosis, the left atrium progressively dilates and may harbor mural thrombi that can embolize . Long-standing congestive changes in the lungs may induce pulmonary vascular and parenchymal changes; over time, these can lead to right ventricular hypertrophy . The left ventricle is largely unaffected by isolated pure mitral stenosis . Microscopically, valves show the organization of the acute inflammation , with postinflammatory neovascularization and transmural fibrosis that obliterate the leaflet architecture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fishmouth or buttonhole deformity seen. Correct . Option: B. Left atrium progressively dilates and harbors mural thrombi. Correct . Option: D. Acute inflammation, with post-inflammatory neovascularization and transmural fibrosis obliterate the leaflet. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Secondary Prophylaxis for patients with RHD: Category Dusation prophylacil 1. Rheumatic fever (without carditis · 5 year after last attack Or · 21 years of age (whichever is longer) 2. Rheumatic fever carditis (without residual valve disease) · 10year after last attack Or · 21 years of age (whichever is longer) 3. Rheumatic fever with persistent Valvular disease (clinical or echo based) · 10year after last attack Or · 21 years of age (whichever is longer)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 12-year-old male patient had a throat infection two to three weeks back and now presented with fever and joint pain. A cardiac biopsy is shown in the figure, identifying the lesion based on the histological picture.", "options": [{"label": "A", "text": "Aschoff bodies", "correct": true}, {"label": "B", "text": "Mac Callum patch", "correct": false}, {"label": "C", "text": "Verrucae", "correct": false}, {"label": "D", "text": "Carditis", "correct": false}], "correct_answer": "A. Aschoff bodies", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831435772-QTDP095005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Aschoff bodies History is highly suggestive of RHD, as the patient is a child with a history of throat infection two to three weeks back and now presenting with fever and joint pain. Histopath image is that of Aschoff bodies .</p>\n<p><strong>Highyeild:</strong></p><p>Rheumatic Heart Disease: Acute immunologically mediated multisystem inflammatory disease due to Group A β Hemolytic Streptococci . Starts at 7-21 days after pharyngitis . Age commonly affected: 5- 10 years Type 2 Hypersensitivity reaction Distinctive lesions in the heart—called Aschoff bodies —are composed of foci of T lymphocytes, occasional plasma cells , and plump activated macrophages called Anitschkow cells . These macrophages have abundant cytoplasm and central round-to-ovoid nuclei (occasionally binucleate) in which the chromatin condenses into a central, slender, wavy ribbon (hence the designation “ caterpillar cells ”). During acute Rheumatic Fever (RF), diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ). Inflammation of the endocardium and the left-sided valves typically results in fibrinoid necrosis within the cusps or tendinous cords. Overlying these necrotic foci and along the lines of closure are small (1 to 2 mm) vegetations, called verrucae . Subendocardial lesions, perhaps exacerbated by regurgitant jets, can induce irregular thickenings called MacCallum plaques , usually in the left atrium . The cardinal anatomic changes of the mitral valve in chronic RHD are leaflet thickening , commissural fusion and shortening , and thickening and fusion of the tendinous cords . The mitral valve is virtually always involved in chronic RHD ; it is affected in isolation in roughly two-thirds of cases, and along with the aortic valve in another 25%. Tricuspid valve involvement is infrequent, and the pulmonary valve is only rarely affected In rheumatic mitral stenosis, calcification and fibrous bridging across the valvular commissures create “ fish mouth ” stenoses . With tight mitral stenosis, the left atrium progressively dilates and may harbor mural thrombi that can embolize . Long-standing congestive changes in the lungs may induce pulmonary vascular and parenchymal changes; over time, these can lead to right ventricular hypertrophy . The left ventricle is largely unaffected by isolated pure mitral stenosis . Microscopically, valves show the organization of the acute inflammation , with postinflammatory neovascularization and transmural fibrosis that obliterate the leaflet architecture.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Mac Callum patch. Incorrect , Subendocardial lesions, seen as irregular thickenings called MacCallum plaques , usually in the left atrium . Option: C. Verrucae. Incorrect , small, warty vegetations along the lines of closure of the valve leaflets are called Verrucae . Option: D. Carditis. Incorrect , during acute RF, diffuse inflammation and Aschoff bodies may be found in any of the three layers of the heart , resulting in pericarditis, myocarditis, or endocarditis ( pancarditis ).</p>\n<p><strong>Extraedge:</strong></p><p>Secondary Prophylaxis for patients with RHD: Category Dusation prophylacil 1. Rheumatic fever (without carditis · 5 year after last attack Or · 21 years of age (whichever is longer) 2. Rheumatic fever carditis (without residual valve disease) · 10year after last attack Or · 21 years of age (whichever is longer) 3. Rheumatic fever with persistent Valvular disease (clinical or echo based) · 10year after last attack Or · 21 years of age (whichever is longer)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding shock associated with systemic inflammation except:", "options": [{"label": "A", "text": "Occurs due to massive haemorrhage and fluid loss", "correct": true}, {"label": "B", "text": "It leads to a massive outpouring of inflammatory mediators", "correct": false}, {"label": "C", "text": "There is vasodilation, venous pooling and increased permeability of the vessels", "correct": false}, {"label": "D", "text": "Metabolic derangement and organ dysfunction can also be seen", "correct": false}], "correct_answer": "A. Occurs due to massive haemorrhage and fluid loss", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Occurs due to massive haemorrhage and fluid loss This is true for Hemorrhagic/Hypovolemic shock, not shock associated with systemic inflammation.</p>\n<p><strong>Highyeild:</strong></p><p>Shock is a state of circulatory failure that impairs tissue perfusion and leads to cellular hypoxia . Initially, the cellular injury is reversible; however, prolonged shock eventually leads to irreversible tissue injury and can be fatal . Causes of shock fall into three general categories: Cardiogenic shock results from low cardiac output due to myocardial pump failure . This can be due to: Intrinsic myocardial damage (infarction), ventricular arrhythmias Extrinsic compression (cardiac tamponade) Outflow obstruction (e.g., pulmonary embolism). Hypovolemic shock results from low cardiac output due to low blood volumes , such as can occur with massive haemorrhage or fluid loss from severe burns . Sepsis, septic shock, and systemic inflammatory response syndrome are interrelated and somewhat overlapping conditions. Sepsis is a life-threatening organ dysfunction caused by a dysregulated host response to infection . Neurogenic shock occurs in the setting of a spinal cord injury, or Anaphylactic shock , an IgE-mediated hypersensitivity reaction. In both of these forms of shock, acute vasodilation leads to hypotension and tissue hypoperfusion . Shock associated with systemic inflammation may be triggered by various insults, particularly microbial infections, burns, trauma, and pancreatitis . The common pathogenic feature is a massive outpouring of inflammatory mediators from innate and adaptive immune cells that produce arterial vasodilation , vascular leakage , and venous blood pooling . These cardiovascular abnormalities result in tissue hypoperfusion , cellular hypoxia , and metabolic derangements that lead to organ dysfunction and, if severe and persistent, organ failure and death . REMEMBER: Neurogenic shock presents with Hypotension and Bradycardia , and other types of shock present with Hypotension and Tachycardia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. It leads to a massive outpouring of inflammatory mediators. True for Septic shock . Option: C. There is vasodilation, venous pooling and increased permeability of the vessels. True for Septic shock . Option: D. Metabolic derangement and organ dysfunction can also be seen. True for Septic shock .</p>\n<p><strong>Extraedge:</strong></p><p>Grades of Hemorrhagic/Hypovolemic shock: Features Minimal/ Grade I Mild/Grade II Moderate/Grade III Severe/Grade IV Blood loss < 750 ml < 15% < 750-1500 ml 15-30% 1500-2000 ml > 30-40% > 2000 ml > 40% Heart rate (bpm) < 100 100-120 120-140 > 140 Respiratory rate (per minute) < 20 20-30 30-40 > 40 Pulse Pressure (SBP - DBP) normal or increased low very low very very low Hypotension (SBP ≤ 90 mmHg) Absent Absent Present Present Base deficit (mEq/L) 0 to -2 -2 to -6 -6 to -10 < -10 Need for blood transfusion Monitor for the need for blood transfusion Possible Yes Massive transfusion</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which one of the listed receptors is the type of receptor on leukocytes that binds to pathogen-associated molecular patterns (PAMP) and mediates the immune response to bacterial lipopolysaccharide?", "options": [{"label": "A", "text": "Cytokines receptor", "correct": false}, {"label": "B", "text": "G protein-coupled receptor", "correct": false}, {"label": "C", "text": "Mannose receptor", "correct": false}, {"label": "D", "text": "Toll-like receptor", "correct": true}], "correct_answer": "D. Toll-like receptor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Toll-like receptor Pathophysiology of septic shock includes the following: Inflammatory and counter-inflammatory responses. Likely initiators of inflammation in sepsis are signalling pathways downstream of Toll-like receptors (TLRs) , which recognise a host of microbe-derived substances containing so-called pathogen-associated molecular patterns (PAMPs) . Endothelial activation and injury. Induction of a procoagulant state. Metabolic abnormalities. Organ dysfunction.</p>\n<p><strong>Highyeild:</strong></p><p>Shock is a state of circulatory failure that impairs tissue perfusion and leads to cellular hypoxia . Initially, the cellular injury is reversible; however, prolonged shock eventually leads to irreversible tissue injury and can be fatal . Causes of shock fall into three general categories: Cardiogenic shock results from low cardiac output due to myocardial pump failure . This can be due to: Intrinsic myocardial damage (infarction), ventricular arrhythmias Extrinsic compression (cardiac tamponade) Outflow obstruction (e.g., pulmonary embolism). Hypovolemic shock results from low cardiac output due to low blood volumes , such as can occur with massive haemorrhage or fluid loss from severe burns . Sepsis, septic shock, and systemic inflammatory response syndrome are interrelated and somewhat overlapping conditions. Sepsis is a life-threatening organ dysfunction caused by a dysregulated host response to infection . Neurogenic shock occurs in the setting of a spinal cord injury, or Anaphylactic shock , an IgE-mediated hypersensitivity reaction. In both of these forms of shock, acute vasodilation leads to hypotension and tissue hypoperfusion . Shock associated with systemic inflammation may be triggered by various insults, particularly microbial infections, burns, trauma, and pancreatitis . The common pathogenic feature is a massive outpouring of inflammatory mediators from innate and adaptive immune cells that produce arterial vasodilation , vascular leakage , and venous blood pooling . These cardiovascular abnormalities result in tissue hypoperfusion , cellular hypoxia , and metabolic derangements that lead to organ dysfunction and, if severe and persistent, organ failure and death . REMEMBER: Neurogenic shock presents with Hypotension and Bradycardia , and other types of shock present with Hypotension and Tachycardia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Cytokines receptor. Incorrect . Option: B. G protein-coupled receptor. Incorrect . Option: C. Mannose receptor. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Grades of Hemorrhagic/Hypovolemic shock: Features Minimal/ Grade I Mild/Grade II Moderate/Grade III Severe/Grade IV Blood loss < 750 ml < 15% < 750-1500 ml 15-30% 1500-2000 ml > 30-40% > 2000 ml > 40% Heart rate (bpm) < 100 100-120 120-140 > 140 Respiratory rate (per minute) < 20 20-30 30-40 > 40 Pulse Pressure (SBP - DBP) normal or increased low very low very very low Hypotension (SBP ≤ 90 mmHg) Absent Absent Present Present Base deficit (mEq/L) 0 to -2 -2 to -6 -6 to -10 < -10 Need for blood transfusion Monitor for the need for blood transfusion Possible Yes Massive transfusion</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of these are metabolic abnormalities seen in the shock patient except", "options": [{"label": "A", "text": "Insulin resistance", "correct": false}, {"label": "B", "text": "Impairment of receptor of IGF-1", "correct": true}, {"label": "C", "text": "Hyperglycaemia", "correct": false}, {"label": "D", "text": "Adrenal insufficiency can occur", "correct": false}], "correct_answer": "B. Impairment of receptor of IGF-1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Impairment of receptor of IGF-1 Septic patients exhibit insulin resistance and hyperglycemia . Cytokines such as TNF and IL-1 , stress-induced hormones (such as glucagon , growth hormone , and glucocorticoids ), and catecholamines all drive gluconeogenesis. At the same time, the pro-inflammatory cytokines suppress insulin release while simultaneously promoting insulin resistance in the liver and other tissues, likely by impairing the surface expression of GLUT-4, a glucose transporter . Hyperglycemia decreases neutrophil function—thereby suppressing bactericidal activity—and causes increased adhesion molecule expression on endothelial cells. Although sepsis is initially associated with an acute surge in glucocorticoid production , this phase may be followed by adrenal insufficiency and a functional deficit of glucocorticoids . This may stem from depression of the synthetic capacity of intact adrenal glands or frank adrenal necrosis resulting from DIC ( Waterhouse-Friderichsen syndrome )—finally, cellular hypoxia and diminished oxidative phosphorylation lead to increased lactate production and lactic acidosis .</p>\n<p><strong>Highyeild:</strong></p><p>Shock is a state of circulatory failure that impairs tissue perfusion and leads to cellular hypoxia . Initially, the cellular injury is reversible; however, prolonged shock eventually leads to irreversible tissue injury and can be fatal . Causes of shock fall into three general categories: Cardiogenic shock results from low cardiac output due to myocardial pump failure . This can be due to: Intrinsic myocardial damage (infarction), ventricular arrhythmias Extrinsic compression (cardiac tamponade) Outflow obstruction (e.g., pulmonary embolism). Hypovolemic shock results from low cardiac output due to low blood volumes , such as can occur with massive haemorrhage or fluid loss from severe burns . Sepsis, septic shock, and systemic inflammatory response syndrome are interrelated and somewhat overlapping conditions. Sepsis is a life-threatening organ dysfunction caused by a dysregulated host response to infection . Neurogenic shock occurs in the setting of a spinal cord injury, or Anaphylactic shock , an IgE-mediated hypersensitivity reaction. In both of these forms of shock, acute vasodilation leads to hypotension and tissue hypoperfusion . Shock associated with systemic inflammation may be triggered by various insults, particularly microbial infections, burns, trauma, and pancreatitis . The common pathogenic feature is a massive outpouring of inflammatory mediators from innate and adaptive immune cells that produce arterial vasodilation , vascular leakage , and venous blood pooling . These cardiovascular abnormalities result in tissue hypoperfusion , cellular hypoxia , and metabolic derangements that lead to organ dysfunction and, if severe and persistent, organ failure and death . REMEMBER: Neurogenic shock presents with Hypotension and Bradycardia , and other types of shock present with Hypotension and Tachycardia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Insulin resistance. Correct . Option: C. Hyperglycaemia. Correct . Option: D. Adrenal insufficiency can occur. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Grades of Hemorrhagic/Hypovolemic shock: Features Minimal/ Grade I Mild/Grade II Moderate/Grade III Severe/Grade IV Blood loss < 750 ml < 15% < 750-1500 ml 15-30% 1500-2000 ml > 30-40% > 2000 ml > 40% Heart rate (bpm) < 100 100-120 120-140 > 140 Respiratory rate (per minute) < 20 20-30 30-40 > 40 Pulse Pressure (SBP - DBP) normal or increased low very low very very low Hypotension (SBP ≤ 90 mmHg) Absent Absent Present Present Base deficit (mEq/L) 0 to -2 -2 to -6 -6 to -10 < -10 Need for blood transfusion Monitor for the need for blood transfusion Possible Yes Massive transfusion</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding stages of shock except:", "options": [{"label": "A", "text": "Non-progressive stage- neurohumoral mechanism set into action", "correct": false}, {"label": "B", "text": "Progressive stage- worsening of circulatory and metabolic imbalance", "correct": false}, {"label": "C", "text": "Progressive stage- deactivation of catecholamine, RAS, baroreceptor receptor", "correct": true}, {"label": "D", "text": "Irreversible stage- severe cellular and tissue injury with chances of minimal survival", "correct": false}], "correct_answer": "C. Progressive stage- deactivation of catecholamine, RAS, baroreceptor receptor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Progressive stage- deactivation of catecholamine, RAS, baroreceptor receptor</p>\n<p><strong>Highyeild:</strong></p><p>Shock is a progressive disorder that leads to death if the underlying problems are not corrected. These stages have been documented most clearly in hypovolemic shock but are common in other forms as well: An initial nonprogressive stage during which reflex compensatory mechanisms are activated and vital organ perfusion is maintained. A progressive stage characterised by tissue hypoperfusion and the onset of worsening circulatory and metabolic derangement , including acidosis An irreversible stage in which cellular and tissue injury is so severe that even if the hemodynamic defects are corrected, survival is not possible In the early nonprogressive phase of shock , various neurohumoral mechanisms help maintain cardiac output and blood pressure . These include baroreceptor reflexes, catecholamine release, activation of the renin-angiotensin axis, ADH release, and generalised sympathetic stimulation . The net effect is tachycardia , peripheral vasoconstriction , and renal fluid conservation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Non-progressive stage- neurohumoral mechanism set into action. True . Option: B. Progressive stage- worsening of circulatory and metabolic imbalance. True . Option: D. Irreversible stage- severe cellular and tissue injury with chances of minimal survival. True .</p>\n<p><strong>Extraedge:</strong></p><p>The cellular and tissue effects of shock are those of hypoxic injury caused by a combination of hypoperfusion and microvascular thrombosis . Although any organ can be affected, the brain, heart, kidneys, adrenals, and gastrointestinal tract are most commonly involved . Fibrin thrombi can form in any tissue but typically are most readily visualised in kidney glomeruli . The kidneys usually exhibit acute tubular necrosis . Adrenal cortical cell lipid depletion is akin to all forms of stress and reflects increased use of stored lipids for steroid synthesis . Whereas the lungs resist hypoxic injury in hypovolemic shock after haemorrhage , sepsis or trauma can precipitate diffuse alveolar damage , leading to the so-called “ shock lung .” Except for neuronal and cardiomyocyte loss, affected tissues can recover completely if the patient survives .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the histological features of shock, except", "options": [{"label": "A", "text": "Adrenal gland shows depletion of lipids in cortical cells", "correct": false}, {"label": "B", "text": "Kidney shows acute tubular necrosis", "correct": false}, {"label": "C", "text": "In septic shock lung shows diffuse alveolar damage", "correct": false}, {"label": "D", "text": "Neuron and myocytes ischemic loss be reverted back", "correct": true}], "correct_answer": "D. Neuron and myocytes ischemic loss be reverted back", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neuron and myocytes ischemic loss be reverted back The cellular and tissue effects of shock are essentially those of hypoxic injury caused by a combination of hypoperfusion and microvascular thrombosis . Although any organ can be affected, the brain, heart, kidneys, adrenals, and gastrointestinal tract are most commonly involved . Fibrin thrombi can form in any tissue but typically are most readily visualised in kidney glomeruli . The kidneys usually exhibit acute tubular necrosis . Adrenal cortical cell lipid depletion is akin to all forms of stress and reflects increased use of stored lipids for steroid synthesis . Whereas the lungs resist hypoxic injury in hypovolemic shock after haemorrhage , sepsis or trauma can precipitate diffuse alveolar damage , leading to the so-called “ shock lung .” Except for neuronal and cardiomyocyte loss, affected tissues can recover completely if the patient survives .</p>\n<p><strong>Highyeild:</strong></p><p>Shock is a state of circulatory failure that impairs tissue perfusion and leads to cellular hypoxia . Initially, the cellular injury is reversible; however, prolonged shock eventually leads to irreversible tissue injury and can be fatal . Causes of shock fall into three general categories: Cardiogenic shock results from low cardiac output due to myocardial pump failure . This can be due to: Intrinsic myocardial damage (infarction), ventricular arrhythmias Extrinsic compression (cardiac tamponade) Outflow obstruction (e.g., pulmonary embolism). Hypovolemic shock results from low cardiac output due to low blood volumes , such as can occur with massive haemorrhage or fluid loss from severe burns . Sepsis, septic shock, and systemic inflammatory response syndrome are interrelated and somewhat overlapping conditions. Sepsis is a life-threatening organ dysfunction caused by a dysregulated host response to infection . Neurogenic shock occurs in the setting of a spinal cord injury, or Anaphylactic shock , an IgE-mediated hypersensitivity reaction. In both of these forms of shock, acute vasodilation leads to hypotension and tissue hypoperfusion . Shock associated with systemic inflammation may be triggered by various insults, particularly microbial infections, burns, trauma, and pancreatitis . The common pathogenic feature is a massive outpouring of inflammatory mediators from innate and adaptive immune cells that produce arterial vasodilation , vascular leakage , and venous blood pooling . These cardiovascular abnormalities result in tissue hypoperfusion , cellular hypoxia , and metabolic derangements that lead to organ dysfunction and, if severe and persistent, organ failure and death . REMEMBER: Neurogenic shock presents with Hypotension and Bradycardia , and other types of shock present with Hypotension and Tachycardia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Adrenal gland shows a depletion of lipids in cortical cells. Correct . Option: B. Kidney shows acute tubular necrosis. Correct . Option: C. In septic shock, the lung shows diffuse alveolar damage. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Grades of Hemorrhagic/Hypovolemic shock: Features Minimal/ Grade I Mild/Grade II Moderate/Grade III Severe/Grade IV Blood loss < 750 ml < 15% < 750-1500 ml 15-30% 1500-2000 ml > 30-40% > 2000 ml > 40% Heart rate (bpm) < 100 100-120 120-140 > 140 Respiratory rate (per minute) < 20 20-30 30-40 > 40 Pulse Pressure (SBP - DBP) normal or increased low very low very very low Hypotension (SBP ≤ 90 mmHg) Absent Absent Present Present Base deficit (mEq/L) 0 to -2 -2 to -6 -6 to -10 < -10 Need for blood transfusion Monitor for the need for blood transfusion Possible Yes Massive transfusion</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 15 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The histopathological findings from a duodenal biopsy from a 38-year-old female with a 2 months history of diarrhea, bloating, and unintentional weight loss are shown below. Intraepithelial lymphocytes ( CD8+) express which cell maker in this condition?", "options": [{"label": "A", "text": "NSP 4", "correct": false}, {"label": "B", "text": "IL 15", "correct": false}, {"label": "C", "text": "NKG2D", "correct": true}, {"label": "D", "text": "IFN gamma", "correct": false}], "correct_answer": "C. NKG2D", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157374144-QTDP113001IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>NKG2D The given clinical history of diarrhea and weight loss and a histopathological image showing villus atrophy and crypt hyperplasia is suggestive of Celiac disease. It is caused by the immune system's reaction to gluten, which damages the lining of the small intestine. Intraepithelial lymphocytes (IELs), a type of CD8+ T cell in the small intestine, are involved in this process. IELs express a cell surface receptor called NKG2D , which binds to stress-induced ligands on epithelial cells, contributing to the damage</p>\n<p><strong>Highyeild:</strong></p><p>Celiac disease Aka Gluten-sensitive enteropathy or celiac sprue Cause: Autoimmune-mediated intolerance to gliadin which is a gluten protein found in the BROW diet (Barley, Rye Oats, Wheat) Genetic: Associated with HLA-DQ2, HLA-DQ8 Site affected: Distal duodenum and/or proximal jejunum Feature: Malabsorption and steatorrhea presenting as diarrhea and weight loss Association: Dermatitis herpetiformis Increased risk of developing T- cell lymphoma Decreased bone density Diagnosis: Abnormal D-xylose test Positive IgA tTG , anti-endomysial and anti-deamidated gliadin peptide antibodies</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. NSP4: It is a nonstructural protein of the rotavirus that has been shown to play a role in the pathogenesis of rotavirus infection. Option: B. IL-15: It is a cytokine that is involved in immune regulation and has been implicated in the pathogenesis of celiac disease. But IL-15 is not a cell marker Option:D. IFN-gamma: It is a cytokine that is produced by T cells and plays a role in immune defense against infections. It is not a cell marker.</p>\n<p><strong>Extraedge:</strong></p><p>MARSH grading It is used to subclassify celiac disease based on features of Intraepithelial lymphocytes, crypt hyperplasia, and villous atrophy.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of celiac disease except:", "options": [{"label": "A", "text": "Increased Intraepithelial lymphocytes", "correct": false}, {"label": "B", "text": "Crypt hyperplasia", "correct": false}, {"label": "C", "text": "Villous atrophy", "correct": false}, {"label": "D", "text": "Increase in mucosal thickness", "correct": true}], "correct_answer": "D. Increase in mucosal thickness", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increase in mucosal thickness Celiac disease may be associated with mucosal inflammation but there is no increased mucosal thickness , rather there is a loss of mucosal and brush-border surface area which probably accounts for the malabsorption.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following antibodies is not associated with celiac disease?", "options": [{"label": "A", "text": "Anti-gliadin antibodies", "correct": false}, {"label": "B", "text": "Anti-tissue transglutaminase antibodies", "correct": false}, {"label": "C", "text": "Antinuclear antibody", "correct": true}, {"label": "D", "text": "Anti-endomysial antibodies", "correct": false}], "correct_answer": "C. Antinuclear antibody", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Antinuclear antibody ANA is a type of autoantibody that is found in individuals with autoimmune diseases such as systemic lupus erythematosus (SLE) and rheumatoid arthritis (RA), but it is not typically associated with celiac disease.</p>\n<p><strong>Highyeild:</strong></p><p>Celiac disease Aka Gluten-sensitive enteropathy or celiac sprue Cause: Autoimmune-mediated intolerance to gliadin which is a gluten protein found in the BROW diet (Barley, Rye Oats, Wheat) Genetic: Associated with HLA-DQ2, HLA-DQ8 Site affected: Distal duodenum and/or proximal jejunum Feature: Malabsorption and steatorrhea presenting as diarrhea and weight loss Association: Dermatitis herpetiformis Increased risk of developing T- cell lymphoma Decreased bone density Diagnosis: Abnormal D-xylose test Positive IgA tTG , anti-endomysial and anti-deamidated gliadin peptide antibodies</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which is the cause of malabsorption in Whipple's disease?", "options": [{"label": "A", "text": "Impaired transepithelial transport", "correct": false}, {"label": "B", "text": "Impaired lymphatic transport", "correct": true}, {"label": "C", "text": "Impaired terminal digestion", "correct": false}, {"label": "D", "text": "Impaired intraluminal digestion", "correct": false}], "correct_answer": "B. Impaired lymphatic transport", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Impaired lymphatic transport Malabsorption in Whipple's disease is caused by impaired lymphatic transpor t due to the infiltration of the intestinal wall by foamy macrophages containing the bacterium Tropheryma whipplei. This results in the obstruction of the lymphatic vessels, leading to impaired fat absorption and subsequent malabsorption syndrome.</p>\n<p><strong>Highyeild:</strong></p><p>Whipple disease Cause: Infection with Treponema Whipplei It can affect multiple organ systems including the gastrointestinal tract, joints, central nervous system, and heart. C ardiac symptoms ( m/c endocarditis ), A rthralgias and N eurological symptom ( m/c progressive dementia ) { CAN symptoms } Diarrhea/steatorrhea occurs later in the disease course. PAS + foamy macrophages in intestinal lamina propria, mesenteric nodes. They contain diastase-resistant granules that represent lysosomes stuffed with partially digested bacteria. Impaired lymphatic transport -Treatment: Induction phase: Ceftriaxone or Meropenem Maintenance phase: TMP/SMX for 1-year</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Impaired transepithelial transport:Transepithelial transport refers to the movement of substances across the epithelial cells that line the intestinal wall. It is not the primary cause of malabsorption in Whipple's disease. Option: C. Impaired terminal digestion: It refers to the malfunctioning of the final stages of the digestive process, particularly the breakdown and absorption of nutrients in the small intestine. It is not a cause of malabsorption in whipple’s disease. Option: D. Impaired intraluminal digestion: It refers to the initial stages of digestion that occur within the intestinal lumen, such as the breakdown of food by enzymes. It is not the primary cause of malabsorption in Whipple's disease.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old patient presented with diarrhea, weight loss, and arthralgia. An intestinal biopsy was performed and a diagram of which is given below. Based on the histological features what is your diagnosis?", "options": [{"label": "A", "text": "Amebiasis", "correct": false}, {"label": "B", "text": "Crohn disease", "correct": false}, {"label": "C", "text": "Whipple disease", "correct": true}, {"label": "D", "text": "Enteric fever", "correct": false}], "correct_answer": "C. Whipple disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Whipple disease The given clinical scenario with a history of diarrhea, weight loss, and arthralgia and a histopathological image showing foamy macrophages suggests the diagnosis</p>\n<p><strong>Highyeild:</strong></p><p>Whipple disease Cause: Infection with Treponema Whipplei It can affect multiple organ systems including the gastrointestinal tract, joints, central nervous system, and heart. C ardiac symptoms ( m/c endocarditis ), A rthralgias and N eurological symptom ( m/c progressive dementia ) { CAN symptoms } Diarrhea/steatorrhea occurs later in the disease course. PAS + foamy macrophages in intestinal lamina propria, mesenteric nodes. They contain diastase-resistant granules that represent lysosomes stuffed with partially digested bacteria. Impaired lymphatic transport -Treatment: Induction phase: Ceftriaxone or Meropenem Maintenance phase: TMP/SMX for 1-year</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Amebiasis: It is a parasitic infection caused by the protozoan Entamoeba histolytica.Histological features in amebiasis typically show necrosis and inflammation of the intestinal wall, with the presence of trophozoites and cysts. Option: B. Crohn's disease: It is a chronic inflammatory bowel disease. Histological features of Crohn's disease typically show granulomas. Option: D. Enteric fever: It is a bacterial infection caused by Salmonella typhi or Paratyphi. Histological features in enteric fever typically show inflammation of the intestinal wall with ulceration.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements regarding hyperplastic polyps is false?", "options": [{"label": "A", "text": "More commonly found in the left colon", "correct": false}, {"label": "B", "text": "Typically less than 5mm in size", "correct": false}, {"label": "C", "text": "Histologically composed of mature goblet and absorptive cells", "correct": false}, {"label": "D", "text": "These polyps have high malignant potential", "correct": true}], "correct_answer": "D. These polyps have high malignant potential", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>These polyps have high malignant potential Hyperplastic polyps are benign colorectal polyps with a very low risk of malignant potential.</p>\n<p><strong>Highyeild:</strong></p><p>Hyperplastic colorectal polyps These are the most common type of colorectal polyps , accounting for approximately 70-80% of all polyps. Size: Typically small - less than 5mm Common in the 6th-7th decade Feature: Round or slightly flattened growths that arise from the lining of the colon or rectum. Most common site: Left colon- including the rectum, sigmoid colon, and descending colon. Histological feature : These are composed of mature goblet and absorptive cells , and have a serrated appearance under the microscope. No malignant potential , and are often considered benign and clinically insignificant. Management: conservative</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following statements is not true regarding Juvenile Polyposis?", "options": [{"label": "A", "text": "Rectum is the most common site of polyp", "correct": false}, {"label": "B", "text": "Associated SMAD 4 mutation", "correct": false}, {"label": "C", "text": "Cystically dilated glands with mucus seen histologically", "correct": false}, {"label": "D", "text": "Common after 10 years of age", "correct": true}], "correct_answer": "D. Common after 10 years of age", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Common after 10 years of age The polyps in Juvenile Polyposis develop in children or young adults, usually in children <5 years of age.</p>\n<p><strong>Highyeild:</strong></p><p>Juvenile polyposis syndrome Numerous non-neoplastic hamartomatous polyps along the GI tract Cause: BMPR1A and SMAD4 mutation Autosomal dominant inheritance Commonly seen in children , <5 years of age Most common site: Rectum Features: Hematochezia , anemia symptoms, abdominal pain, rectal prolapse, diarrhea Histopathological findings: Polyp shows abundant edematous stroma and dilated cystic spaces filled with mucin. Management: Polypectomy, surgical colectomy</p>\n<p><strong>Extraedge:</strong></p><p>Criteria for diagnosis: > Five juvenile polyps in colon/rectum (3-100) Multiple juvenile polyps in other areas of the GI tract Family history with any number of polyps</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 28-year-old female presents with a history of recurrent abdominal pain, vomiting, and dark-colored stools. She has a history of multiple polyps in the small intestine and pigmented lesions on her lips and oral mucosa. Which of the following syndromes is most likely responsible for her symptoms?", "options": [{"label": "A", "text": "Lynch syndrome", "correct": false}, {"label": "B", "text": "Cowden syndrome", "correct": false}, {"label": "C", "text": "Peutz-Jeghers syndrome", "correct": true}, {"label": "D", "text": "Gardner syndrome", "correct": false}], "correct_answer": "C. Peutz-Jeghers syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Peutz-Jeghers syndrome The given clinical history is suggestive of Peutz-jeers syndrome. PJS is characterized by the presence of hamartomatous polyps in the gastrointestinal tract, which can cause abdominal pain, obstruction, and bleeding. Additionally, the patient's history of pigmented macules on her buccal mucosa and lower lip is consistent with the mucocutaneous pigmentation commonly seen in PJS</p>\n<p><strong>Highyeild:</strong></p><p>Peutz-jeers syndrome Autosomal dominant inherited condition Cause: Loss of function mutation of STK11(LKB1) Common in 5 to 10 years of age Most common site of polyps: Jejunum Features: Multiple GI polyps and pigmented lesions around oral mucosa ( perioral melanosis) Very high risk of extracolonic malignant transformation Pancreatic cancers (100%) Breast, Ovarian, and Cervical cancers Thyroid cancer</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Lynch syndrome: It is a hereditary cancer syndrome that predisposes individuals to colorectal and other cancers, but it does not typically present with pigmented macules. Option: B . Cowden syndrome: It is characterized by multiple hamartomas and an increased risk of breast, thyroid, and other cancers, but it does not typically present with intestinal polyps. Option: D. Gardner syndrome: It is a subtype of familial adenomatous polyposis (FAP) that is characterized by the presence of extraintestinal manifestations, such as osteomas and soft tissue tumors, in addition to the intestinal polyps seen in FAP.</p>\n<p><strong>Extraedge:</strong></p><p>Histopathological feature: Multiple polyps in arborizing pattern (tree-like)- large and pedunculated with a lobulated contour. Glands are lined by normal-appearing intestinal epithelium. Management: Polypectomy</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the mentioned syndromes have autosomal dominant patterns of inheritance except:", "options": [{"label": "A", "text": "Cowden syndrome", "correct": false}, {"label": "B", "text": "Peutz jeghers syndrome", "correct": false}, {"label": "C", "text": "Cronkhite Canada syndrome", "correct": true}, {"label": "D", "text": "Gardner syndrome", "correct": false}], "correct_answer": "C. Cronkhite Canada syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cronkhite Canada syndrome Cronkhite Canada syndrome is a rare, non-inherited disorder that is characterized by the development of multiple gastrointestinal polyps along with other symptoms such as hair loss, nail abnormalities, and skin pigmentation changes.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Cowden syndrome: It is inherited in an autosomal dominant pattern and is caused by mutations in the PTEN gene, which is a tumor suppressor gene. People with Cowden syndrome have an increased risk of developing several types of cancer, including breast, thyroid, and endometrial cancer. Option: B. Peutz-Jeghers syndrome: It is also inherited in an autosomal dominant pattern. It is caused by mutations in the STK11 gene, which is a tumor suppressor gene. Option: D. Gardner syndrome: It is inherited in an autosomal dominant pattern caused by mutations in the APC gene, which is also associated with familial adenomatous polyposis (FAP). It presents with multiple polyps in the colon and rectum and has an increased risk of developing colon cancer. Patients may also develop noncancerous desmoid tumors, in other parts of the body.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 3-year-old child presented with a pedunculated rectal polyp. Polypectomy was done and sent for histopathological examination, a picture of which is given below, classify the type of polyp:", "options": [{"label": "A", "text": "Juvenile rectal polyp", "correct": true}, {"label": "B", "text": "Tubular adenoma", "correct": false}, {"label": "C", "text": "Serrated adenoma", "correct": false}, {"label": "D", "text": "Peutz jeghers polyp", "correct": false}], "correct_answer": "A. Juvenile rectal polyp", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157376730-QTDP113010IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Juvenile rectal polyp The given clinical history and a histopathological image showing dilated glands filled with mucin is suggestive of a Juvenile rectal polyp. Juvenile polyps are the most common type of colorectal polyps in children , and they are usually pedunculated with a smooth surface. Usually <3cm in diameter Histologically, they are characterized by cystically dilated glands lined by normal-appearing epithelium. These polyps are benign and usually do not require any further intervention after polypectomy.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Tubular adenoma: It is a type of polyp found in adults, not typically in children. It is characterized by glands that are elongated and straight, with the lining epithelium showing varying degrees of dysplasia. Option: C. Serrated adenoma: It is a type of colorectal polyp that is often associated with microsatellite instability and BRAF mutations. It is not typically seen in children. Option: D. Peutz-Jeghers polyp: It is a hamartomatous polyp associated with Peutz-Jeghers syndrome. It is characterized by smooth muscle, glandular tissue, and an admixture of other tissue types. Peutz-Jeghers syndrome is an inherited disorder and is not typically seen in young children presenting with a single polyp.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "By analyzing the histological features of adenoma classify it into its subclass:", "options": [{"label": "A", "text": "Tubular adenoma", "correct": false}, {"label": "B", "text": "Villous adenoma", "correct": true}, {"label": "C", "text": "Tubulovillous adenoma", "correct": false}, {"label": "D", "text": "Sessile serrated adenoma", "correct": false}], "correct_answer": "B. Villous adenoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157378204-QTDP113012IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Villous adenoma The given histopathological image of the polyp showing finger-like projection is of a Villous adenoma. Villous adenoma have highest malignant potential</p>\n<p><strong>Random:</strong></p><p>Explanation of other options: Adenomas can be classified as: Villous adenoma: A polyp with more than 75% villous features Tubular adenoma: Mainly comprised of tubular glands and have less than 25% villous features Tubulovillous adenoma: An adenoma with both tubular and villous features Sessile serrated adenomas are a recognized precursor of colorectal cancer. Histologically, they are defined by: Abnormal crypt architecture with dilatation of the crypt bases Excessive luminal serrations Absence of cytological atypia Sessile serrated adenomas with dysplasia are advanced lesions with a high risk of rapid progression to malignancy. They are considered to have an increased propensity to transform to adenocarcinoma. Sessile serrated adenomas are relatively subtle in appearance. They tend to be small (around 5 millimeters), flat or just slightly raised (“sessile”) and the same color as the surrounding tissue, with vaguely defined borders.</p>\n<p><strong>Table:</strong></p><p>Types\n of adenomatous polyp Types of adenomatous polyp Feature Tubular Adenomas Most common type of adenomatous polyp, composed of glandular\n structures resembling the normal intestinal glands Villous Adenomas It is composed of finger-like projections with a high risk of\n malignant potential Tubulovillous Adenomas Contain both glandular structures and finger-like projections Sessile Serrated Adenomas Flat or sessile polyps with saw-toothed glandular structures,\n associated with an increased risk of developing cancer in the right colon Traditional Serrated Adenomas Characterized by a saw-toothed appearance of the glandular structures,\n typically found in the left colon and rectum</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is a characteristic feature of Familial adenomatous polyposis?", "options": [{"label": "A", "text": "Multiple adenomatous polyps in the colon", "correct": true}, {"label": "B", "text": "Single large adenomatous polyp in the colon", "correct": false}, {"label": "C", "text": "Lipomatous polyps in the colon", "correct": false}, {"label": "D", "text": "Hyperplastic polyps in the colon", "correct": false}], "correct_answer": "A. Multiple adenomatous polyps in the colon", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Multiple adenomatous polyps in the colon Multiple adenomatous polyps in the colon is a characteristic feature of Familial adenomatous polyposis.</p>\n<p><strong>Highyeild:</strong></p><p>Familial Adenomatous Polyposis It is an autosomal dominant condition that results in the development of Multiple adenomatous polyps in the colon and rectum. Cause: Mutations in the APC gene, which is a tumor suppressor gene on chr 5q21-q22. ( 2 hit hypothesis) The risk of developing colorectal cancer in individuals with FAP is nearly 100% if prophylactic colectomy is not performed. Other features: Congenital hypertrophy of the retinal pigment epithelium (CHRPE), desmoid tumors, osteomas, epidermoid cysts, brain and thyroid tumors, etc. Screening for FAP: Colonoscopy with biopsy to evaluate for the presence of polyps, as well as genetic testing to identify the APC gene mutation. Treatment: Prophylactic colectomy with ileorectal anastomosis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Single large adenomatous polyp in the colon: Adenomatous polyposis syndrome is characterized by the presence of multiple adenomatous polyps, rather than a single large polyp. Option: C. Lipomatous polyps in the colon: Lipomatous polyps are rare and benign tumors composed of adipose tissue. They are not typically associated with adenomatous polyposis syndrome. Option: D. Hyperplastic polyps in the colon: These are also benign tumors, but they are not typically associated with adenomatous polyposis syndrome. They are more commonly found in the distal colon and rectum, and they are not associated with an increased risk of developing colon cancer.</p>\n<p><strong>Extraedge:</strong></p><p>Attenuated FAP Less severe form of FAP <100 adenomas Size of adenomas /< 1 cm until adulthood Right-sided adenomas</p>\n<p><strong>Table:</strong></p><p>Criteria\nfor diagnosis of Familial Adenomatous Polyposis: Any\none of the following: 1. Germline mutation in APC gene 2. >/100 colorectal adenomatous polyps 3. Any colorectal adenoma <30 years in a patient\nwith a family history of FAP 4. Intra-abdominal desmoid fibromatosis,\nosteomas, epidermoid cysts with family history of FAP.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old female presents with a history of endometrial cancer, and on further questioning, you learn that her father was diagnosed with colon cancer at the age of 60. Based on this information, which of the following conditions should you consider as a potential diagnosis?", "options": [{"label": "A", "text": "Familial Adenomatous Polyposis", "correct": false}, {"label": "B", "text": "Lynch syndrome", "correct": true}, {"label": "C", "text": "Peutz-Jeghers syndrome", "correct": false}, {"label": "D", "text": "Cowden syndrome.", "correct": false}], "correct_answer": "B. Lynch syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lynch syndrome The given clinical history of endometrial cancer, in addition to a family history of colon cancer, suggests the diagnosis of Hereditary non-polyposis colorectal cancer (HNPCC), also known as Lynch syndrome. It was originally described based on familial clustering of cancers at several sites including the colorectum, endometrium, stomach, ovary, ureters, brain, small bowel, hepatobiliary tract, pancreas, and skin.</p>\n<p><strong>Highyeild:</strong></p><p>Lynch syndrome Aka HNPCC- Hereditary non-polyposis colorectal cancer Autosomal dominant inherited disorder. Mutations in genes involved in DNA repair. The most common genes mutated in HNPCC are MSH2 and MLH1 with subsequent microsatellite instability , which is involved in DNA mismatch repair. Site: proximal colon is always involved Associated with endometrial, ovarian, and skin cancers.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Familial Adenomatous Polyposis (FAP): It is a hereditary condition characterized by the presence of numerous adenomatous polyps in the colon, which typically develop in adolescence or early adulthood. It is not associated with endometrial cancer or other extracolonic malignancies. Option: C. Peutz-Jeghers syndrome: It is a hereditary condition characterized by the presence of multiple gastrointestinal polyps and pigmented lesions on the lips, oral mucosa, and digits. Endometrial cancer is not commonly associated with Peutz-Jeghers syndrome. Option: D. Cowden syndrome: It is a hereditary condition caused by a mutation in PTEN gene that predisposes individuals to multiple benign and malignant tumors, including breast, thyroid, GI, and endometrial cancers. It is typically not associated with colorectal cancers.</p>\n<p><strong>Extraedge:</strong></p><p>Onset of colorectal cancer occurs at an early age (avg 45 years) HPE of lynch-syndrome related colorectal tumours: Poorly Differentiated, mutinous, signet-cell feature</p>\n<p><strong>Table:</strong></p><p>DNA REPAIR AND ASSOCIATED DISEASES</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following genes is commonly mutated in patients with HNPCC (Hereditary Non-Polyposis Colorectal Cancer)?", "options": [{"label": "A", "text": "TP53", "correct": false}, {"label": "B", "text": "APC", "correct": false}, {"label": "C", "text": "MSH2", "correct": true}, {"label": "D", "text": "KRAS", "correct": false}], "correct_answer": "C. MSH2", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MSH2 HNPCC is a hereditary condition that predisposes individuals to colorectal cancer and other malignancies. It is caused by inherited mutations in genes involved in DNA repair. The most common genes mutated in HNPCC are MSH2 and MLH1, which are involved in DNA mismatch repair. Colon cancers in HNPCC patients tend to occur at younger ages than sporadic colon cancers and are often located in the right colon.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. TP53: It is a tumor suppressor gene\nthat is commonly mutated in many types of cancer. Mutations in the TP53 gene are the\nmost commonly acquired mutations in cancer. Somatic mutations in p53 are found\nin approximately 50% of all human cancers. The frequency varies according to\ntumor type. For example, the frequency ranges from about: 10% in leukemia 20% in breast cancer 30% in gastric cancers Up to 60% in ovarian and colorectal\ncancers. Option: B. APC: It is a tumor suppressor gene that is commonly mutated in familial adenomatous polyposis (FAP), another inherited condition that predisposes individuals to colorectal cancer. Option: D. KRAS: It is a proto-oncogene that is commonly mutated in sporadic (non-hereditary) cases of colorectal cancer.</p>\n<p><strong>Table:</strong></p><p>DNA REPAIR AND ASSOCIATED DISEASES</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Colonic biopsy from a patient presented with bleeding per rectum and change in bowel habits from 1-2 years. HPE picture shown below, what is your diagnosis based on the histological findings?", "options": [{"label": "A", "text": "Squamous cell carcinoma", "correct": false}, {"label": "B", "text": "Adenocarcinoma", "correct": true}, {"label": "C", "text": "Lymphoma", "correct": false}, {"label": "D", "text": "Carcinoid tumor", "correct": false}], "correct_answer": "B. Adenocarcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689157379130-QTDP113017IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Adenocarcinoma The given clinical history of bleeding per rectum with HPE showing tall columnar cells that resemble dysplastic epithelium is indicative of glandular tissue undergoing malignant transformation. Hence, the diagnosis is Adenocarcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Adenoma to Adenocarcinoma sequence</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Squamous cell carcinoma: It is an unlikely diagnosis because it is not a common type of colorectal cancer. Squamous cell carcinoma usually occurs in the anal canal, not in the colon. Option: C. Colorectal lymphomas: It accounts for only 0.2-1% of all colorectal malignancies. Additionally, lymphomas would have different histological features. Option: D. Carcinoid tumors are rare: These are slow-growing tumors that can occur in the gastrointestinal tract, including the colon. It presents with symptoms such as flushing, diarrhea, and wheezing due to the release of hormones like serotonin.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which gene is first mutated in adenoma to adenocarcinoma sequence?", "options": [{"label": "A", "text": "TP 53", "correct": false}, {"label": "B", "text": "APC", "correct": true}, {"label": "C", "text": "MLH 1", "correct": false}, {"label": "D", "text": "KRAS", "correct": false}], "correct_answer": "B. APC", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>APC The adenoma to adenocarcinoma sequence is a process of tumorigenesis in which a normal glandular tissue progresses to adenoma, and then to adenocarcinoma through a series of genetic mutations. The first mutatio n in this sequence is a loss of function mutation in the APC (Adenomatous polyposis coli) gene, which leads to the formation of adenomas. Subsequent mutation s in other genes, such as KRAS, TP53, and MLH1 , lead to the progression of adenomas to adenocarcinomas.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 26 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Intra tubular germ cell neoplasia is implicated as a cause for the following testicular tumour?", "options": [{"label": "A", "text": "Pediatric yolk sac tumours", "correct": false}, {"label": "B", "text": "Pediatric teratomas", "correct": false}, {"label": "C", "text": "Seminomas", "correct": true}, {"label": "D", "text": "Adult spermatocytic seminomas", "correct": false}], "correct_answer": "C. Seminomas", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Seminomas Intratubular germ cell neoplasia (ITGCN), also known as carcinoma in situ of the testis, is a precursor lesion to invasive germ cell tumours, especially seminomas . ITGCN is characterized by malignant germ cells confined to the seminiferous tubules , without invasion into the surrounding tissue. ITGCN is believed to be the precursor lesion to 50-70% of cases of classical seminoma.</p>\n<p><strong>Highyeild:</strong></p><p>Seminoma Seminomas are malignant tumours that arise from the germ cells of the seminiferous tubules of the testis. They are the commonest variety of testicular tumour Age: 30 to 50 years of age Risk factor: Undescended testis Analogous to ovarian dysgerminoma Does not occur in infancy Highly radiosensitive Late metastasis, excellent prognosis Histology: Large cells in lobules with watery cytoplasm and “ fried egg appearance” . Tumour marker: PLAP</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Pediatric yolk sac tumours: These tumours arise from primitive germ cells and are not associated with intratubular germ cell neoplasia. Option: B. Pediatric teratomas: These tumours arise from totipotent germ cells and are not associated with intratubular germ cell neoplasia. Option: D. Adult spermatocytic seminomas: These tumours are rare and arise from spermatogonia. They are not associated with intratubular germ cell neoplasia.</p>\n<p><strong>Extraedge:</strong></p><p>Types of seminoma Types of seminoma Microscopic features Tumour markers Classical Seminoma Large cells with prominent nuclei and clear cytoplasm arranged in lobules separated by fibrous septa; lymphocytic infiltrates are present Elevated levels of lactate dehydrogenase (LDH) and placental alkaline phosphatase (PLAP) Anaplastic Seminoma Composed of undifferentiated cells, prominent nucleoli, and large multinucleated giant cells; necrosis is present Elevated levels of lactate dehydrogenase (LDH) and placental alkaline phosphatase (PLAP) Spermatocytic Seminoma Three cell types (small, intermediate, and large) with round nuclei and clear cytoplasm; no fibrous septa or lymphocytic infiltrates Normal levels of tumour markers</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All the following are testicular dysgenesis syndromes except:", "options": [{"label": "A", "text": "Cryptorchidism", "correct": false}, {"label": "B", "text": "Epispadias", "correct": true}, {"label": "C", "text": "Poor sperm quality", "correct": false}, {"label": "D", "text": "Hypospadias", "correct": false}], "correct_answer": "B. Epispadias", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Epispadias Epispadias is not a testicular dysgenesis syndrome . It is a congenital anomaly where the urethra opens on the dorsal side of the penis due to incomplete fusion of the urethral folds.</p>\n<p><strong>Highyeild:</strong></p><p>Testicular dysgenesis syndrome(TDS) It is a term used to describe a group of conditions that arise from abnormal fetal testicular development. Some of the key features of TDS are: Cryptorchidism : Undescended testis or testes that have not migrated to the scrotum. Hypospadias : A congenital condition where the opening of the urethra is on the underside of the penis instead of the tip. Poor sperm quality : Men with TDS may have poor semen quality, including low sperm count, decreased sperm motility, and abnormal sperm morphology. Leydig cell hypoplasia: A rare genetic disorder that affects the production of testosterone by the Leydig cells in the testes. Testicular germ cell tumours : Men with TDS have an increased risk of developing testicular germ cells tumours such as seminoma and non-seminoma. Male infertility : TDS is one of the major causes of male infertility.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A., C., D: All are part of testicular dysgenesis syndrome</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the most common testicular tumour seen in children?", "options": [{"label": "A", "text": "Yolk sac tumour", "correct": true}, {"label": "B", "text": "Choriocarcinoma", "correct": false}, {"label": "C", "text": "Teratoma", "correct": false}, {"label": "D", "text": "Seminoma", "correct": false}], "correct_answer": "A. Yolk sac tumour", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Yolk sac tumour Yolk sac tumour is the most common testicular tumour in children, accounting for approximately 60-80% of cases. This tumour is typically seen in children younger than 3 years of age and is characterized by the presence of Schiller-Duval bodies on histology.</p>\n<p><strong>Highyeild:</strong></p><p>Yolk sac tumour Aka endodermal sinus tumour It is a malignant germ cell tumour . It is the most common testicular tumour in children <3 years old Histology: Schiller-Duval bodies or glomeruloid structures [structures resembling endodermal sinuses]. Tumour marker – AFP These have an excellent prognosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Choriocarcinoma: It is a rare testicular tumour, accounting for less than 1% of cases. It is characterized by the presence of syncytiotrophoblastic and cytotrophoblastic cells in histology. Option: C. Teratoma: It is the second most common testicular tumour in children, accounting for approximately 10-30% of cases. It is characterized by the presence of multiple tissue types on histology, including elements from all three germ cell layers. Option: D. Seminoma: It is a testicular tumour that is more commonly seen in adults than in children. It is typically slow-growing and has a good prognosis with treatment. It is characterized by the presence of uniform, round, or polygonal cells in histology.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Histopathological findings of a testicular tumour are shown below. What is the most likely diagnosis?", "options": [{"label": "A", "text": "Choriocarcinoma", "correct": false}, {"label": "B", "text": "Embryonal cell Ca", "correct": false}, {"label": "C", "text": "Endodermal sinus tumour", "correct": true}, {"label": "D", "text": "Immature teratoma", "correct": false}], "correct_answer": "C. Endodermal sinus tumour", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689160880616-QTDP149005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Endodermal sinus tumour The given histopathological image shows Schiller-Duvall bodies which is a characteristic feature of endodermal sinus tumour, also known as yolk sac tumour.</p>\n<p><strong>Highyeild:</strong></p><p>Yolk sac tumour Aka endodermal sinus tumour It is a malignant germ cell tumour . It is the most common testicular tumour in children <3 years old Histology: Schiller-Duval bodies or glomeruloid structures [structures resembling endodermal sinuses]. Tumour marker – AFP These have an excellent prognosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Choriocarcinoma: It is characterized by the presence of both cytotrophoblast and syncytiotrophoblast cells, but not Schiller-Duvall bodies. Option: B. Embryonal cell carcinoma: This tumour is characterized by the presence of primitive embryonal cells with large nuclei and scant cytoplasm. The Schiller-Duval bodies are not a characteristic feature of this tumour. Option:D. Immature teratoma: This tumour is composed of tissues from all three germ cell layers (endoderm, mesoderm, and ectoderm) and is characterized by the presence of immature or embryonic elements. The Schiller-Duval bodies are not typically seen in this tumour.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All are germ cell tumours except-", "options": [{"label": "A", "text": "Seminoma", "correct": false}, {"label": "B", "text": "Leydig cell tumour", "correct": true}, {"label": "C", "text": "Embryonal carcinoma", "correct": false}, {"label": "D", "text": "Endodermal sinus tumor", "correct": false}], "correct_answer": "B. Leydig cell tumour", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Leydig cell tumour Leydig cell tumour is not a germ cell tumour, but a sex cord-stromal tumour of the testis. It arises from the Leydig cells, which produce testosterone.</p>\n<p><strong>Highyeild:</strong></p><p>Leydig cell tumour Most common non-germ cell testicular tumour Benign tumour 1 - 3 % of all testicular tumours 5-10% are bilateral The Cut surface is a small, yellow well-circumscribed lesion , without haemorrhage or necrosis Microscopically fusiform-shaped cytoplasmic inclusion bodies (Reinke crystals) are pathognomonic It produces androgens or estrogens leading to precocious puberty and gynecomastia</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:A., C., D: Seminoma, embryonal carcinoma, and endodermal sinus tumour, are all types of germ cell tumors.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Microscopic features of seminoma include all of the following except:", "options": [{"label": "A", "text": "Gland formation", "correct": true}, {"label": "B", "text": "Lymphocytic infiltration", "correct": false}, {"label": "C", "text": "Monomorphic cells", "correct": false}, {"label": "D", "text": "Destruction of seminiferous tubules", "correct": false}], "correct_answer": "A. Gland formation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Gland formation Seminoma does not show gland formation , but instead, it causes the destruction of the seminiferous tubules.</p>\n<p><strong>Highyeild:</strong></p><p>Morphology of Seminoma Sheets of Monomorphic cells Sheets divided into poorly demarcated lobules by septa of fibrous tissue Septa show lymphocytic infiltration (T lymphocytes) Classic seminoma cell - large and round to polyhedral and has a distinct cell membrane; Clear or watery-appearing cytoplasm ; Cytoplasm contains glycogen. Large, central nucleus with one or two prominent nucleoli</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Lymphocytic infiltration: This is a characteristic feature of a seminoma. Seminomas are usually infiltrated by lymphocytes, which can be used as a diagnostic feature to differentiate them from other testicular tumours. Option:C. Monomorphic cells: Seminomas are composed of cells that are morphologically similar to each other, which is why they are called \"monomorphic.\" This feature helps to distinguish seminomas from other types of testicular tumours, which can have more variable cell types and architecture. Option:D. Destruction of seminiferous tubules: Seminomas usually arise from germ cells within the seminiferous tubules. As the tumour grows, it can replace and destroy the surrounding tubules.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "True about serum AFP level:", "options": [{"label": "A", "text": "Raised in testicular tumour", "correct": false}, {"label": "B", "text": "Raised in 70% of cases of HCC", "correct": false}, {"label": "C", "text": "Correlation between tumour recurrence after surgery in HCC", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above Alpha-Fetoprotein is a normal fetal serum protein synthesized by the liver, yolk sac, and gastrointestinal tract that shares sequence homology with albumin. Increased levels are seen in Omphalocele Hepatocellular carcinoma/hepatoma Hepatoblastoma Neural tube defects: a-fetoprotein in amniotic fluid and maternal serum Non-seminomatous germ cell tumours (Option: A) Yolk sac tumour Immature teratoma (rarely)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Tumour marker for Endodermal Sinus Tumour:", "options": [{"label": "A", "text": "PLAP", "correct": false}, {"label": "B", "text": "HCG", "correct": false}, {"label": "C", "text": "Alfa fetoprotein", "correct": true}, {"label": "D", "text": "Cytokeratin", "correct": false}], "correct_answer": "C. Alfa fetoprotein", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Alfa fetoprotein Alpha-fetoprotein (AFP) is a tumour marker that is commonly elevated in patients with endodermal sinus tumours, also known as yolk sac tumours. Elevated levels of AFP may also be seen in other types of germ cell tumours and certain liver diseases.</p>\n<p><strong>Highyeild:</strong></p><p>Yolk sac tumour Aka endodermal sinus tumour It is a malignant germ cell tumour . It is the most common testicular tumour in children <3 years old Histology: Schiller-Duval bodies or glomeruloid structures [structures resembling endodermal sinuses]. Tumour marker – AFP These have an excellent prognosis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. PLAP: It (placental alkaline phosphatase) is a tumour marker that is often elevated in patients with seminoma. Option: B. HCG: It (human chorionic gonadotropin) is a tumour marker that is often elevated in patients with choriocarcinoma and some cases of non-seminomatous germ cell tumours. Option: D. Cytokeratin: It is a protein found in many types of cells and is not specific to any particular type of tumour.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is not a risk factor for developing testicular carcinoma?", "options": [{"label": "A", "text": "Klinefelter syndrome", "correct": false}, {"label": "B", "text": "Undescended testis", "correct": false}, {"label": "C", "text": "History of contralateral testicular tumour", "correct": false}, {"label": "D", "text": "Benzopyrene exposure", "correct": true}], "correct_answer": "D. Benzopyrene exposure", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Benzopyrene exposure Benzopyrene exposure is a risk factor for other cancers, such as lung cancer and skin cancer, but not for testicular carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Risk factors for developing testicular carcinoma: Cryptorchidism (undescended testis) Family history of testicular cancer Personal history of testicular cancer Klinefelter syndrome (47, XXY) Infertility or subfertility History of testicular atrophy or maldescent Prior testicular biopsy Maternal exposure to diethylstilbestrol (DES) Environmental exposure to certain chemicals such as benzene and pesticides HIV infection and AIDS Caucasian race (higher incidence among white men than among men of other races)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The commonest site for extragonadal germ cell tumour is:", "options": [{"label": "A", "text": "Retroperitoneum", "correct": false}, {"label": "B", "text": "Sacrococcygeal region", "correct": false}, {"label": "C", "text": "Pineal gland", "correct": false}, {"label": "D", "text": "Mediastinum", "correct": true}], "correct_answer": "D. Mediastinum", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mediastinum The commonest site for extragonadal germ cell tumour- Mediastinum It is usually seen in Klinefelter syndrome.</p>\n<p><strong>Highyeild:</strong></p><p>Sites of extragonadal germ cell tumours Mediastinum : This is the most common site of extragonadal germ cell tumours, accounting for approximately 50% of cases. The tumours typically arise in the anterior mediastinum and can present with symptoms related to compression of adjacent structures. Retroperitoneum : Retroperitoneal germ cell tumours account for approximately 25-30% of cases. They can be difficult to diagnose early, as they may not cause symptoms until they have grown quite large. Sacrococcygeal region: This is the most common site of extragonadal germ cell tumours in infants and young children. These tumours are often diagnosed shortly after birth and are typically benign. Central nervous system (CNS): Germ cell tumours can also arise in the CNS, typically in the pineal gland or in the suprasellar region. These tumours can cause a variety of neurological symptoms. Other sites: Germ cell tumours can also occur in the ovary, testis, and other locations, although these are considered to be gonadal tumours rather than extragonadal tumours.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Infertility is a common feature in “Sertoli cell only” syndrome because -", "options": [{"label": "A", "text": "Too many Sertoli cells inhibit spermatogenesis via inhibin", "correct": false}, {"label": "B", "text": "Proper blood-testis barrier is not established", "correct": false}, {"label": "C", "text": "There is no germ cell in this condition", "correct": true}, {"label": "D", "text": "Sufficient numbers of spermatozoa are not produced", "correct": false}], "correct_answer": "C. There is no germ cell in this condition", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>There is no germ cell in this condition Sertoli cell-only syndrome (also known as germ cell aplasia) is a condition in which there are no germ cells (sperm-producing cells) present in the seminiferous tubules of the testes. This leads to infertility because sperm cannot be produced in the absence of germ cells.</p>\n<p><strong>Highyeild:</strong></p><p>Sertoli-cell-only (SCO) syndrome Also known as germ cell aplasia The testes are usually small to normal in size Testes in which only Sertoli cells line the seminiferous tubules No germ cells are seen which are involved in spermatogenesis Leydig cells are normally reduced or absent Normal secondary male features</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which testicular tumour is the most common in adults among the following Options:", "options": [{"label": "A", "text": "Seminoma", "correct": true}, {"label": "B", "text": "Teratoma", "correct": false}, {"label": "C", "text": "Yolk sac tumour", "correct": false}, {"label": "D", "text": "Dysgerminoma", "correct": false}], "correct_answer": "A. Seminoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Seminoma Seminoma is the most common type of testicular tumour in adults, accounting for about 40-50% of all cases. Most common testicular tumour in infants –YST Most common testicular tumour in adults - seminoma Most common testicular tumour adults –Lymphoma</p>\n<p><strong>Highyeild:</strong></p><p>Seminoma Seminomas are malignant tumours that arise from the germ cells of the seminiferous tubules of the testis. They are the commonest variety of testicular tumour Age: 30 to 50 years of age Risk factor: Undescended testis Analogous to ovarian dysgerminoma Does not occur in infancy Highly radiosensitive Late metastasis, excellent prognosis Histology: Large cells in lobules with watery cytoplasm and “ fried egg appearance” . Tumour marker: PLAP</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Teratoma: Although teratoma is a common type of testicular tumour, it is more commonly seen in infants and children, rather than adults. Option: C. Yolk sac tumour: Yolk sac tumours are rare in adult testicles, and are more commonly seen in infants and children. Option: D. Dysgerminoma: Dysgerminoma is a tumour of the ovary, and is not found in male testicles.</p>\n<p><strong>Extraedge:</strong></p><p>Types of seminoma Types of seminoma Microscopic features Tumour markers Classical Seminoma Large cells with prominent nuclei and clear cytoplasm arranged in lobules separated by fibrous septa; lymphocytic infiltrates are present Elevated levels of lactate dehydrogenase (LDH) and placental alkaline phosphatase (PLAP) Anaplastic Seminoma Composed of undifferentiated cells, prominent nucleoli, and large multinucleated giant cells; necrosis is present Elevated levels of lactate dehydrogenase (LDH) and placental alkaline phosphatase (PLAP) Spermatocytic Seminoma Three cell types (small, intermediate, and large) with round nuclei and clear cytoplasm; no fibrous septa or lymphocytic infiltrates Normal levels of tumour markers</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A patient with a right-sided testicular tumour is being evaluated for metastasis. Which group of lymph nodes is most likely to get involved first?", "options": [{"label": "A", "text": "Para-aortic lymph nodes", "correct": false}, {"label": "B", "text": "Preaortic lymph nodes", "correct": false}, {"label": "C", "text": "Superficial inguinal lymph nodes", "correct": false}, {"label": "D", "text": "Inter-aortocaval nodes", "correct": true}], "correct_answer": "D. Inter-aortocaval nodes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Inter-aortocaval nodes Inter-aortocaval nodes are the first group of lymph nodes that receive lymphatic drainage from the testes and thus are the most likely to be involved in metastasis from a right-sided testicular tumour.</p>\n<p><strong>Highyeild:</strong></p><p>Metastasis of testicular tumour Lymphatic spread is the most common mode of metastasis in testicular tumours , with the para-aortic lymph nodes being the first group of lymph nodes to be involved. Hematogenous spread can also occur, most commonly to the lungs and liver. Right-sided tumours metastasize primarily to inter-aortocaval nodes Left-sided tumours metastasise primarily to the left para-aortic nodes</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Testicular involvement without epididymitis is a feature of-", "options": [{"label": "A", "text": "Gonorrhoea", "correct": false}, {"label": "B", "text": "Syphilis", "correct": true}, {"label": "C", "text": "Tuberculosis", "correct": false}, {"label": "D", "text": "Granuloma inguinale", "correct": false}], "correct_answer": "B. Syphilis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Syphilis Testicular involvement without epididymitis is a feature of syphilis . It is known as syphilitic orchitis and is a rare manifestation of syphilis. It is usually seen in the late stage of the disease and can present as a painless enlargement of one or both testes. Other features of late syphilis include gummatous lesions, neurosyphilis, and cardiovascular syphilis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Gonorrhoea: It can cause epididymitis, which is inflammation of the epididymis, but it does not usually involve the testis. Option: C. Tuberculosis: It can cause epididymitis and testicular involvement, but it is more commonly associated with epididymal involvement. Option: D. Granuloma inguinale: It is a chronic bacterial infection caused by Klebsiella granulomatis and can cause genital ulcers, but it does not usually involve the testes or epididymis.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 24 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "False statement regarding antiphospholipid antibodies is", "options": [{"label": "A", "text": "It is also known as lupus anticoagulant syndrome", "correct": false}, {"label": "B", "text": "In this, fetal loss occur due to thrombosis of placental vessels", "correct": true}, {"label": "C", "text": "It is a known cause of renal microangiopathy", "correct": false}, {"label": "D", "text": "Its clinical manifestations include recurrent abortion, thrombosis, repeated miscarriages and cardiac valve vegetation", "correct": false}], "correct_answer": "B. In this, fetal loss occur due to thrombosis of placental vessels", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>In this, fetal loss occur due to thrombosis of placental vessels Antiphospholipid antibody (APLA) APLA is an autoimmune disorder characterised by: Presence of one or more antiphospholipid (aPL) autoantibodies Venous or arterial thromboses , or pregnancy complications such as recurrent miscarriages, unexplained fetal death, and premature birth.</p>\n<p><strong>Highyeild:</strong></p><p>Antiphospholipid antibody (APLA) This syndrome (previously called the lupus anticoagulant syndrome) has variable clinical manifestations, including recurrent thromboses, repeated miscarriages, cardiac valve vegetations, and thrombocytopenia . Fetal loss does not appear to be explained by thrombosis . Instead, it stems from antibody-mediated interference with the growth and differentiation of trophoblasts , leading to a failure of placentation. Antiphospholipid antibody syndrome is also a cause of renal microangiopathy , resulting in renal failure associated with multiple capillary and arterial thrombosis. Clinical presentations can include pulmonary embolism , pulmonary hypertension , valvular heart disease, stroke , bowel infarction , or renovascular hypertension . Anti–β2 -glycoprotein antibodies are suspected to have a significant role in APLA. Diagnosis of APLA is based on clinical features and demonstration of aPL antibodies in the serum. Management of APLA involves various forms of anticoagulation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is also known as lupus anticoagulant syndrome. True . Option: C. It is a known cause of renal microangiopathy. True . Option: D. Its clinical manifestations include recurrent abortion, thrombosis, repeated miscarriages and cardiac valve vegetation. True .</p>\n<p><strong>Extraedge:</strong></p><p>The antibodies in patients with APLA also frequently result in a false-positive serologic test for syphilis because the antigen in the standard assay is embedded in cardiolipin, which cross-reacts with phospholipids of Treponema pallidum.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The suspected antigen for Ab formation is beta-two glycoprotein 1, and it is associated with the surface of all of the following except:", "options": [{"label": "A", "text": "Endothelial cells", "correct": false}, {"label": "B", "text": "Trophoblast", "correct": false}, {"label": "C", "text": "Thrombin", "correct": false}, {"label": "D", "text": "Platelets", "correct": true}], "correct_answer": "D. Platelets", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Platelets In APLA, suspected antibody targets include β2- glycoprotein I , a plasma protein that associates with the surfaces of endothelial cells and trophoblasts, and thrombin . In vivo, antibodies are suspected to bind to these and perhaps other proteins, thereby inducing a hypercoagulable state through uncertain mechanisms.</p>\n<p><strong>Highyeild:</strong></p><p>Antiphospholipid antibody (APLA) This syndrome (previously called the lupus anticoagulant syndrome) has variable clinical manifestations, including recurrent thromboses, repeated miscarriages, cardiac valve vegetations, and thrombocytopenia . Fetal loss does not appear to be explained by thrombosis . Instead, it seems to stem from antibody-mediated interference with the growth and differentiation of trophoblasts , leading to a failure of placentation. Antiphospholipid antibody syndrome is also a cause of renal microangiopathy , resulting in renal failure associated with multiple capillary and arterial thrombosis. Clinical presentations can include pulmonary embolism , pulmonary hypertension , valvular heart disease, stroke , bowel infarction , or renovascular hypertension . Anti–β2 -glycoprotein antibodies are suspected to have a significant role in APLA. Diagnosis of APLA is based on clinical features and demonstration of aPL antibodies in the serum. Management of APLA involves various forms of anticoagulation .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Endothelial cells. Correct . Option: B. Trophoblast. Correct . Option: C. Thrombin. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>The antibodies in patients with APLA also frequently result in a false-positive serologic test for syphilis because the antigen in the standard assay is embedded in cardiolipin, which cross-reacts with phospholipids of Treponema pallidum.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding hypercoagulability except?", "options": [{"label": "A", "text": "It is also known as thrombophilia", "correct": false}, {"label": "B", "text": "It is associated with endothelial injury and altered blood flow", "correct": false}, {"label": "C", "text": "Most common inherited cause of hypercoagulability is prothrombin mutation", "correct": true}, {"label": "D", "text": "Hypercoagulability can be primary or secondary, depending on the cause", "correct": false}], "correct_answer": "C. Most common inherited cause of hypercoagulability is prothrombin mutation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Most common inherited cause of hypercoagulability is prothrombin mutation Factor V Leiden mutation is the most common cause of hypercoagulability.</p>\n<p><strong>Highyeild:</strong></p><p>Hypercoagulability (also called Thrombophilia) refers to an abnormally high tendency of the blood to clot and is typically caused by alterations in coagulation factors . It is associated with Endothelial injury and altered blood flow .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is also known as thrombophilia. Correct . Option: B. It is associated with endothelial injury and altered blood flow. Correct . Option: D. Hypercoagulability can be primary or secondary, depending on the cause. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Hypercoagulability is significant in venous thrombosis and can be divided into primary (genetic) and secondary (acquired) disorders. Of the inherited causes of hypercoagulability, point mutations in the factor V and prothrombin genes are the most common .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding factor V mutation except:", "options": [{"label": "A", "text": "It is the most common inherited cause of hypercoagulability", "correct": false}, {"label": "B", "text": "60% of cases of Recurrent DVT usually show this mutation", "correct": false}, {"label": "C", "text": "Leiden mutation causes the replacement of arginine with glutamine at amino acid 506", "correct": false}, {"label": "D", "text": "This mutation makes factor V more susceptible to cleavage by protein C", "correct": true}], "correct_answer": "D. This mutation makes factor V more susceptible to cleavage by protein C", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>This mutation makes factor V more susceptible to cleavage by protein C Factor V Leiden mutation is the most common cause of hypercoagulability. It is an autosomal dominant genetic condition that exhibits incomplete penetrance , meaning that not every person with the mutation will develop the disease. Single nucleotide mutation in factor V is called factor V Leiden . Among individuals with recurrent DVT , the frequency of this mutation is considerably higher, approaching 60% . The mutation results in the replacement of arginine with glutamine at amino acid 506 , which renders factor V resistant to cleavage and inactivation by protein C .</p>\n<p><strong>Highyeild:</strong></p><p>Hypercoagulability (also called Thrombophilia) refers to an abnormally high tendency of the blood to clot, and is typically caused by alterations in coagulation factors . It is associated with Endothelial injury and altered blood flow .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is the most common inherited cause of hypercoagulability. Correct . Option: B. 60% of cases of Recurrent DVT usually show this mutation. Correct . Option: C. Leiden mutation causes the replacement of arginine with glutamine at amino acid 506. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Hypercoagulability is significant in venous thrombosis and can be divided into primary (genetic) and secondary (acquired) disorders. Of the inherited causes of hypercoagulability, point mutations in the factor V and prothrombin genes are the most common .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which condition, inherited as well as acquired, can cause both arterial and venous thrombosis?", "options": [{"label": "A", "text": "Antithrombin III deficiency", "correct": false}, {"label": "B", "text": "Leiden mutation", "correct": false}, {"label": "C", "text": "Homocysteinemia", "correct": true}, {"label": "D", "text": "Protein C deficiency", "correct": false}], "correct_answer": "C. Homocysteinemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Homocysteinemia</p>\n<p><strong>Highyeild:</strong></p><p>Homocysteinemia Elevated levels of homocysteine may be inherited or acquired . An inherited deficiency of cystathionine may cause marked elevations of homocysteine β-synthase . Acquired causes include deficiency of vitamin B6, B12, and folic acid . Prothrombotic effects of homocysteine may be due to thioester linkages formed between homocysteine metabolites and various proteins, including fibrinogen.</p>\n<p><strong>Extraedge:</strong></p><p>Elevated levels of homocysteine contribute to arterial and venous thrombosis and the development of atherosclerosis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding heparin-induced from thrombocytopenia except:", "options": [{"label": "A", "text": "It occurs due to the administration of unfractionated heparin", "correct": false}, {"label": "B", "text": "Due to the formation of antibodies and binding of Ab to platelets and heparin", "correct": false}, {"label": "C", "text": "Heparin administration and low platelet can cause a prothrombotic state", "correct": false}, {"label": "D", "text": "It initiates within a few hours", "correct": true}], "correct_answer": "D. It initiates within a few hours", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It initiates within a few hours Heparin Induced Thrombocytopenia is seen after 4-14 days of heparin exposure .</p>\n<p><strong>Highyeild:</strong></p><p>Heparin Induced Thrombocytopenia (HIT) HIT syndrome is a serious, potentially life-threatening disorder that occurs following the administration of unfractionated heparin . Heparin is a Hapten, e. an incomplete antigen, and when it combines with Platelet Factor 4 (PF4) , it becomes a complete antigen and can lead to the formation of antibodies. PF4 usually is present on the platelet surface . The antibody then combines with this Heparin-PF4 complex on the platelet surface. This is followed by fibrin binding to this complex and forming a clot . This effect on platelets and endothelial damage induced by antibody binding combine to produce a prothrombotic state , even in the face of heparin administration and low platelet counts (as platelets are deposited in the thrombus thus formed). Thus there is Thrombocytopenia which is induced by heparin . This is seen after 4-14 days of heparin exposure .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It occurs due to the administration of unfractionated heparin. Correct . Option: B. Due to the formation of antibodies and binding of Ab to platelets and heparin. Correct . Option: C. Heparin administration and low platelet can cause a prothrombotic state. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Treatment of HIT: Heparin should be discontinued in such cases. Even low molecular weight (LMW) heparins are not safe in such patients, and they should be treated with a direct thrombin inhibitor. Drugs used in the treatment of HIT include: Bivalirudin Argatroban</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following features are true regarding Hashimoto's thyroiditis except:", "options": [{"label": "A", "text": "It is an autoimmune disease", "correct": false}, {"label": "B", "text": "It is the most common cause of hypothyroidism iodine sufficient areas", "correct": false}, {"label": "C", "text": "Antibody against thyroglobulin and thyroid peroxidase is seen", "correct": false}, {"label": "D", "text": "It predisposes to the development of T-cell lymphoma", "correct": true}], "correct_answer": "D. It predisposes to the development of T-cell lymphoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It predisposes to the development of T-cell lymphoma Hashimoto thyroiditis is not typically associated with the predisposition to the development of T-cell lymphoma but is associated with an increased risk of diffuse large B-cell lymphoma.</p>\n<p><strong>Highyeild:</strong></p><p>Hashimoto thyroiditis Aka chronic autoimmune thyroiditis A most common cause of hypothyroidism in iodine-sufficient regions. Associated with HLA-DR3 Increased risk of primary thyroid lymphoma- diffuse large B-cell lymphoma Features: Moderately enlarged, non-tender thyroid May be preceded by transient hyperthyroid state: Hashitoxicosis due to follicular rupture Serology: Antithyroid peroxidase and anti-thyroglobulin antibodies present Histology: Hurthle cells , lymphoid aggregates with germinal centres Treatment: Toxic phrase: Beta-blocker Hypothyroid state: T4 supplements</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A., B., C: All are true</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most common cause of hypothyroidism in iodine-sufficient areas?", "options": [{"label": "A", "text": "Iatrogenic hypothyroidism", "correct": false}, {"label": "B", "text": "Viral Infection induced", "correct": false}, {"label": "C", "text": "Autoimmune hypothyroidism", "correct": true}, {"label": "D", "text": "Dyshormonogenetic goitre", "correct": false}], "correct_answer": "C. Autoimmune hypothyroidism", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Autoimmune hypothyroidism The most common cause of hypothyroidism in iodine-sufficient areas is Autoimmune hypothyroidism, also known as Hashimoto's thyroiditis. This occurs when the immune system attacks the thyroid gland, leading to inflammation and damage to the gland over time.</p>\n<p><strong>Highyeild:</strong></p><p>Hashimoto thyroiditis Aka chronic autoimmune thyroiditis A most common cause of hypothyroidism in iodine-sufficient regions. Associated with HLA-DR3 Increased risk of primary thyroid lymphoma- diffuse large B-cell lymphoma Features: Moderately enlarged, non-tender thyroid May be preceded by transient hyperthyroid state: Hashitoxicosis due to follicular rupture Serology: Antithyroid peroxidase and anti-thyroglobulin antibodies present Histology: Hurthle cells , lymphoid aggregates with germinal centres Treatment: Toxic phase: Beta-blocker Hypothyroid state: T4 supplements</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Iatrogenic hypothyroidism: This refers to hypothyroidism caused by medical treatment such as surgical removal of the thyroid gland, radiation therapy, or administration of certain medications. It is not the most common cause of hypothyroidism in iodine-sufficient areas. Option: B. Viral Infection induced: While certain viral infections can affect thyroid function, they are not the most common cause of hypothyroidism in iodine-sufficient areas. Option: D. Dyshormonogenetic goitre: This refers to a group of genetic disorders that affect the synthesis and/or processing of thyroid hormones. It is a rare cause of hypothyroidism and is not the most common cause in iodine-sufficient areas.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 45-year-old patient presented with features of hypothyroidism from 2-3 years, the histopathology is shown below. Based on histological features, what is your diagnosis?", "options": [{"label": "A", "text": "Hashimoto’s thyroiditis", "correct": true}, {"label": "B", "text": "Granulomatous thyroiditis", "correct": false}, {"label": "C", "text": "Papillary carcinoma", "correct": false}, {"label": "D", "text": "Riders thyroiditis", "correct": false}], "correct_answer": "A. Hashimoto’s thyroiditis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161328717-QTDP163003IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hashimoto’s thyroiditis The given clinical history is suggestive of Hashimoto thyroiditis. The histopathological image shows a mononuclear inflammatory infiltrate of the thyroid parenchyma, containing small lymphocytes, plasma cells, and well-developed germinal centres which are typical of Hashimoto thyroiditis.</p>\n<p><strong>Highyeild:</strong></p><p>Hashimoto thyroiditis Aka chronic autoimmune thyroiditis A most common cause of hypothyroidism in iodine-sufficient regions. Associated with HLA-DR3 Increased risk of primary thyroid lymphoma- diffuse large B-cell lymphoma Features: Moderately enlarged, non-tender thyroid May be preceded by transient hyperthyroid state: Hashitoxicosis due to follicular rupture Serology: Antithyroid peroxidase and anti-thyroglobulin antibodies present Histology: Hurthle cells , lymphoid aggregates with germinal centres Treatment: Toxic phase: Beta-blocker Hypothyroid state: T4 supplements</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Granulomatous thyroiditis: It is ala subacute thyroiditis or de Quervain's thyroiditis which is a self-limited inflammatory disorder of the thyroid gland. Histologically, it is characterized by granulomatous inflammation with giant cells, lymphocytes, and plasma cells. Option: C. Papillary carcinoma: It is a common type of thyroid cancer that arises from the follicular cells of the thyroid gland. Histologically, it is characterized by papillary projections and nuclear changes, such as nuclear grooves and pseudo inclusions. Option: D. Riedel's thyroiditis: It is a rare form of thyroiditis that is characterized by the replacement of the thyroid parenchyma with fibrous tissue. It typically presents with a hard, painless goiter and can be associated with hypothyroidism.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are features of De Quervain thyroiditis except:", "options": [{"label": "A", "text": "In the early phase follicles are disrupted and replaced by neutrophils forming microabscesses", "correct": false}, {"label": "B", "text": "Inflammatory infiltrate composed of lymphocytes, plasma cells, and macrophages with granuloma formation", "correct": false}, {"label": "C", "text": "It is triggered by a bacterial, fungal infection", "correct": true}, {"label": "D", "text": "It is the most common cause of thyroid pain", "correct": false}], "correct_answer": "C. It is triggered by a bacterial, fungal infection", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is triggered by a bacterial, fungal infection De Quervain's thyroiditis is not triggered by a bacterial or fungal infection, but rather it is thought to be triggered by a viral infection.</p>\n<p><strong>Highyeild:</strong></p><p>De Quervian thyroiditis It is aka Sub-acute granulomatous thyroiditis Usually self-limited disease Natural history: Transient hyperthyroidism -> Euthyroid state -> Hypothyroidism -> Euthyroid state Often preceded by a viral infection Features: Very tender thyroid Jaw pain Increased ESR Histology: Granulomatous inflammation Treatment: NSAIDs, Beta blocker</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., D: All are true</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding thyroid adenoma except:", "options": [{"label": "A", "text": "It is a solitary, spherical, and well-encapsulated lesion", "correct": false}, {"label": "B", "text": "Histological composed of uniform appearing follicles that contain colloid", "correct": false}, {"label": "C", "text": "Cystic change, calcification, and hurtle cell change are common", "correct": false}, {"label": "D", "text": "Vascular invasion is commonly seen", "correct": true}], "correct_answer": "D. Vascular invasion is commonly seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Vascular invasion is commonly seen Vascular invasion is a feature of malignancy, and its presence suggests a carcinoma rather than an adenoma.</p>\n<p><strong>Highyeild:</strong></p><p>Thyroid adenoma: It is a benign tumour of the thyroid gland. It is a solitary, well-encapsulated lesio n that is usually spherical in shape. Features Histology: Thyroid adenoma is composed of follicles that contain colloid , which is similar to normal thyroid tissue. Cystic changes, calcification, and Hurthle cell change can occur in thyroid adenomas. Thyroid adenoma can present as a cold nodule on thyroid scintigraphy , but it is usually non-functional and does not produce thyroid hormones. It is usually asymptomatic , but it can cause compressive symptoms if it grows large enough to impinge on adjacent structures. Diagnostic test of choice: Fine-needle aspiration cytology</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., C.: All are true</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following thyroid tumour do not arise from follicular epithelial cell?", "options": [{"label": "A", "text": "Papillary carcinoma", "correct": false}, {"label": "B", "text": "Follicular carcinoma", "correct": false}, {"label": "C", "text": "Medullary carcinoma", "correct": true}, {"label": "D", "text": "Anaplastic carcinoma", "correct": false}], "correct_answer": "C. Medullary carcinoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Medullary carcinoma Medullary carcinoma does not arise from follicular epithelial cells of the thyroid gland. It a rises from parafollicular cells (also called C-cells) of the thyroid gland, which produces and secrete calcitonin, a hormone that regulates calcium metabolism.</p>\n<p><strong>Highyeild:</strong></p><p>Medullary carcinoma Arises from parafollicular “C cells” which produce and secrete calcitonin, a hormone that regulates calcium metabolism. It can be sporadic or hereditary and is usually more aggressive than papillary or follicular carcinoma. Histology: Sheets of polygonal cells in amyloid stromatolites Associated with MEN2A and 2B (RET mutations) Immunohistochemistry: MTC cells typically stain positive for calcitonin, chromogranin, and synaptophysin. Calcitonin and serotonin secreted by MTC are responsible for diarrhoea</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Papillary carcinoma: It is the most common type of thyroid cancer which arises from follicular epithelial cells, which produce and secrete thyroid hormones. Option: B. Follicular carcinoma: It is the second most common type of thyroid carcinoma which also arises from follicular epithelial cells. Option: D. Anaplastic carcinoma: It is a rare but aggressive type of thyroid cancer that arises from follicular epithelial cells and has a very poor prognosis.</p>\n<p><strong>Extraedge:</strong></p><p>Secretions of Medullary thyroid cancer Calcitonin CEA: Carcinoembryonic antigen Calcitonin gene-related peptide Histaminidase Prostaglandins E2 and F2 alpha Serotonin</p>\n<p><strong>Table:</strong></p><p>Types\n of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are cytogenetic abnormalities seen in Papillary carcinoma of the thyroid except:", "options": [{"label": "A", "text": "Rearrangement of RET", "correct": false}, {"label": "B", "text": "Rearrangement of NTRK1", "correct": false}, {"label": "C", "text": "Mutation of BRAF", "correct": false}, {"label": "D", "text": "Mutation of RAS", "correct": true}], "correct_answer": "D. Mutation of RAS", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Mutation of RAS Mutation of RAS is NOT a cytogenetic abnormality typically seen in papillary carcinoma of the thyroid. RAS mutation seen in follicular carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Rearrangement of RET: This is the most common genetic abnormality seen in papillary carcinoma, occurring in about 40-60% of cases. The most common RET rearrangements are RET/PTC1 and RET/PTC3. Option: B. Rearrangement of NTRK1: This genetic abnormality is also associated with papillary carcinoma. Option: C. Mutation of BRAF: This is the second most common genetic abnormality seen in papillary carcinoma, occurring in about 40-45% of cases. The most common BRAF mutation is V600E.</p>\n<p><strong>Table:</strong></p><p>Common\n proto-oncogenes implicated in thyroid carcinoma: Thyroid carcinoma proto-oncogene Papillary RET (RET PTC translocation), NTRK1, BRAF, Follicular PAX8-PPARG, RAS Medullary RET (RET point mutation) Anaplastic TP53, BRAF, RAS Toxic adenoma GNAS mutation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which unique translocation in follicular carcinoma forms the PAX8-PPARG fusion gene?", "options": [{"label": "A", "text": "(2,3)(q13,p25)", "correct": true}, {"label": "B", "text": "(2,5)(p5,q17)", "correct": false}, {"label": "C", "text": "(5,7)(q13,p25)", "correct": false}, {"label": "D", "text": "(8,12)(q13,p25)", "correct": false}], "correct_answer": "A. (2,3)(q13,p25)", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>(2,3)(q13,p25) The unique translocation in follicular carcinoma that forms the PAX8-PPARG fusion gene is (2,3)(q13,p25). This translocation creates a fusion gene composed of portions of PAX8, a paired homeobox gene that is important in thyroid development , and the peroxisome proliferator-activated receptor gene ( PPARG ), whose gene product is a nuclear hormone receptor implicated in the terminal differentiation of cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. (2,5)(p5,q17) - This translocation is associated with Ewing sarcoma, a type of bone cancer that most commonly affects children and young adults. Option: C. (5,7)(q13,p25) - This translocation is associated with acute myeloid leukaemia (AML), a type of blood cancer that affects the bone marrow and blood cells. Option: D. (8,12)(q13,p25) - This translocation is not associated with any specific cancer or disorder, but translocations involving chromosomes 8 and 12 have been reported in various types of cancers, including prostate cancer and leukaemia.</p>\n<p><strong>Table:</strong></p><p>Common\n proto-oncogenes implicated in thyroid carcinoma: Thyroid carcinoma proto-oncogene Papillary RET (RET PTC translocation), NTRK1, BRAF, Follicular PAX8-PPARG, RAS Medullary RET (RET point mutation) Anaplastic TP53, BRAF, RAS Toxic adenoma GNAS mutation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is the most common variant of papillary thyroid cancer?", "options": [{"label": "A", "text": "Clear cell", "correct": false}, {"label": "B", "text": "Tall cell", "correct": false}, {"label": "C", "text": "Cribriform", "correct": false}, {"label": "D", "text": "Follicular", "correct": true}], "correct_answer": "D. Follicular", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Follicular The most common variant of papillary thyroid carcinoma of the thyroid is the follicular variant</p>\n<p><strong>Highyeild:</strong></p><p>Features of Follicular variant of Papillary thyroid carcinoma Characteristic nuclear feature of papillary carcinoma Follicular architecture Can be encapsulated or infiltrative</p>\n<p><strong>Extraedge:</strong></p><p>Variants of papillary thyroid carcinoma Variant Features Follicular ● Most common ● Follicular architecture, nuclear features of PTC Tall-cell ● Cells have a height 2 times the width ● Seen in elderly ● Extrathyroidal extension ● More aggressive, poorer prognosis Diffuse-sclerosing ● Diffuse fibrosis ● Seen in young people ● Lymph nodes metastasis present ● Lacks BRAF mutation Cribriform ● Associated with familial adenomatous polyposis ● Beta-date in mutation Columnar-cell ● Tall columnar cells ● Pseudostratification of nuclei ● Minimal papillary structures Solid ● Seen in children ● Associated with Chernobyl nuclear accident</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of papillary carcinoma of the thyroid except:", "options": [{"label": "A", "text": "Complex branching papillae with fibrovascular core", "correct": false}, {"label": "B", "text": "Orphan Annie’s eye appearance and intranuclear grooves", "correct": false}, {"label": "C", "text": "Psammoma bodies", "correct": false}, {"label": "D", "text": "Propensity for angioinvasion", "correct": true}], "correct_answer": "D. Propensity for angioinvasion", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Propensity for angioinvasion Papillary carcinoma of the thyroid generally does not exhibit a significant propensity for angioinvasion . Follicular carcinoma of the thyroid is the subtype that more commonly invades blood vessels.</p>\n<p><strong>Highyeild:</strong></p><p>Papillary thyroid carcinoma It is the most common type of thyroid cancer, accounting for about 80% of all cases. Associated with a number of genetic alterations, including BRAF and NTRK1 mutations and RET/PTC rearrangements. Other risk factors: Childhood irradiation and thyroglossal cysts, Family history of thyroid cancer, and certain genetic syndromes such as Cowden syndrome and familial adenomatous polyposis. Histological feature: Papillary architecture Psammoma bodies Nuclear grooves and pseudo inclusions Orphan Annie’s eye nuclei Fibrovascular cores Present as a solitary nodule or as a multifocal disease involving both lobes of the thyroid gland. Prognosis: Excellent: a 10-year survival rate of greater than 95%.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Complex branching papillae with a fibrovascular core: These are hallmark features of papillary carcinoma. The papillae are lined by cuboidal to columnar epithelial cells with enlarged nuclei and characteristic nuclear features such as the \"Orphan Annie eye\" appearance and intranuclear grooves. Option: B. Orphan Annie eye and intranuclear groove: orphan Annie eye appearance refers to a nuclear feature in which the chromatin is evenly distributed and forms a clear halo around a central, optically clear nucleolus. Intranuclear grooves refer to nuclear features in which the nuclei of the tumour cells have deep invaginations or clefts, creating grooves or furrows in the nucleus. Option: C. Psammoma bodies are concentrically laminated calcifications that are frequently seen in papillary carcinoma of the thyroid, as well as in other neoplastic and non-neoplastic conditions.</p>\n<p><strong>Extraedge:</strong></p><p>Variants of papillary thyroid carcinoma Variant Features Follicular ● Most common ● Follicular architecture, nuclear features of PTC Tall-cell ● Cells have a height 2 times the width ● Seen in elderly ● Extrathyroidal extension ● More aggressive, poorer prognosis Diffuse-sclerosing ● Diffuse fibrosis ● Seen in young people ● Lymph nodes metastasis present ● Lacks BRAF mutation Cribriform ● Associated with familial adenomatous polyposis ● Beta-date in mutation Columnar-cell ● Tall columnar cells ● Pseudostratification of nuclei ● Minimal papillary structures Solid ● Seen in children ● Associated with Chernobyl nuclear accident</p>\n<p><strong>Table:</strong></p><p>Types of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 24-year-old patient presented with a thyroid nodule, and the ultrasound sound shows calcification. The histological features are shown in the diagram below. What is your diagnosis?", "options": [{"label": "A", "text": "Follicular carcinoma", "correct": false}, {"label": "B", "text": "Medullary carcinoma", "correct": false}, {"label": "C", "text": "Papillary carcinoma", "correct": true}, {"label": "D", "text": "Anaplastic carcinoma", "correct": false}], "correct_answer": "C. Papillary carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161330112-QTDP163011IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Papillary carcinoma The given clinical scenario with a histopathological image showing the presence of branching papillae with a fibrovascular stalk and cuboidal epithelial cells suggests the diagnosis of papillary carcinoma. Additionally, calcifications on ultrasound are also commonly seen in papillary carcinoma.</p>\n<p><strong>Highyeild:</strong></p><p>Papillary thyroid carcinoma It is the most common type of thyroid cancer, accounting for about 80% of all cases. Associated with a number of genetic alterations, including BRAF and NTRK1 mutations and RET/PTC rearrangements. Other risk factors: Childhood irradiation and thyroglossal cysts, Family history of thyroid cancer, and certain genetic syndromes such as Cowden syndrome and familial adenomatous polyposis. Histological feature: Papillary architecture Psammoma bodies Nuclear grooves and pseudo inclusions Orphan Annie’s eye nuclei Fibrovascular cores Present as a solitary nodule or as a multifocal disease involving both lobes of the thyroid gland. Prognosis: Excellent: a 10-year survival rate of greater than 95%.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Follicular carcinoma: It typically presents with a solitary nodule, uniform follicles without colloid, and capsular and/or vascular invasion. Calcification is not a common finding in follicular carcinoma. Option: B . Medullary carcinoma: It is composed of nests of cells that are polygonal in shape, with abundant granular cytoplasm and nuclei that are round to oval in shape. Option: D. Anaplastic carcinoma: It is a highly aggressive malignancy that often presents as a rapidly growing mass with areas of necrosis, haemorrhage, and invasion of surrounding tissues. The cells are typically spindle-shaped and pleomorphic and may show evidence of squamous or giant cell differentiation.</p>\n<p><strong>Table:</strong></p><p>Types\n of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following are features of a diffuse sclerosing variant of papillary carcinoma?", "options": [{"label": "A", "text": "Occurs in young individuals including children", "correct": false}, {"label": "B", "text": "There is extensive fibrosis throughout the gland", "correct": false}, {"label": "C", "text": "It is associated with lymphocytic infiltrate", "correct": false}, {"label": "D", "text": "All of the above", "correct": true}], "correct_answer": "D. All of the above", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All of the above The diffuse sclerosing variant of papillary carcinoma is a rare subtype that typically affects young individuals, including children. It is characterized by the presence of extensive fibrosis throughout the gland, which can make it difficult to diagnose. Additionally, it is often associated with a prominent lymphocytic infiltrate.</p>\n<p><strong>Highyeild:</strong></p><p>Papillary thyroid carcinoma It is the most common type of thyroid cancer, accounting for about 80% of all cases. Associated with a number of genetic alterations, including BRAF and NTRK1 mutations and RET/PTC rearrangements. Other risk factors: Childhood irradiation and thyroglossal cysts, Family history of thyroid cancer, and certain genetic syndromes such as Cowden syndrome and familial adenomatous polyposis. Histological feature: Papillary architecture Psammoma bodies Nuclear grooves and pseudo inclusions Orphan Annie’s eye nuclei Fibrovascular cores Present as a solitary nodule or as a multifocal disease involving both lobes of the thyroid gland. Prognosis: Excellent: a 10-year survival rate of greater than 95%.</p>\n<p><strong>Extraedge:</strong></p><p>Variants of papillary thyroid carcinoma Variant Features Follicular ● Most common ● Follicular architecture, nuclear features of PTC Tall-cell ● Cells have a height 2 times the width ● Seen in elderly ● Extrathyroidal extension ● More aggressive, poorer prognosis Diffuse-sclerosing ● Diffuse fibrosis ● Seen in young people ● Lymph nodes metastasis present ● Lacks BRAF mutation Cribriform ● Associated with familial adenomatous polyposis ● Beta-date in mutation Columnar-cell ● Tall columnar cells ● Pseudostratification of nuclei ● Minimal papillary structures Solid ● Seen in children ● Associated with Chernobyl nuclear accident</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are histological features of follicular carcinoma except:", "options": [{"label": "A", "text": "Capsular and vascular invasion is necessary", "correct": false}, {"label": "B", "text": "Histological show uniform cel forming a repetitive follicular pattern", "correct": false}, {"label": "C", "text": "Intranuclear grooves and pseudo-inclusion seen", "correct": true}, {"label": "D", "text": "Occasionally there is hurthle cell change", "correct": false}], "correct_answer": "C. Intranuclear grooves and pseudo-inclusion seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Intranuclear grooves and pseudo-inclusion seen Intranuclear grooves and pseudo-inclusion are characteristic of papillary carcinoma , not follicular carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B., D: All are true features of follicular carcinoma.</p>\n<p><strong>Table:</strong></p><p>Types\n of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Histological examination of thyroidectomy specimen shown in the diagram, based on the histological features Identify the type of tumour:", "options": [{"label": "A", "text": "Papillary carcinoma", "correct": false}, {"label": "B", "text": "Medullary carcinoma", "correct": false}, {"label": "C", "text": "Follicular carcinoma", "correct": true}, {"label": "D", "text": "Anaplastic carcinoma", "correct": false}], "correct_answer": "C. Follicular carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161331129-QTDP163014IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Follicular carcinoma The histological features shown in the diagram suggest follicular carcinoma of the thyroid. It is characterized by uniform-appearing follicles that invade the thyroid capsule and blood vessel s, and have a propensity for hematogenous spread.</p>\n<p><strong>Highyeild:</strong></p><p>Follicular thyroid carcinoma It is a malignant tumour that arises from follicular cells of the thyroid gland. It presents as a painless nodule in the thyroid gland. Risk factors : History of radiation exposure to the head and neck region, a family history of thyroid cance r, long-standing goitre, iodine deficiency Associated with RAS mutation and PAX8-PPAR-gamma translocation More common in women than men, and the incidence increases with age. Histological features: Follicular architecture, with a follicle surrounded by a single layer of epithelial cells. FTC may be minimally invasive or widely invasive, depending on the extent of invasion of the tumour through the capsule and into surrounding structures. Vascular invasion is a hallmark of malignancy in FTC. FNAC is not useful: cannot distinguish between adenoma and carcinoma</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Papillary carcinoma: It typically presents papillary structures with fibrovascular stalks and characteristic nuclear features like orphan Annie's eye appearance, intranuclear grooves, and pseudo inclusions. Option: B. Medullary carcinoma: It arises from the parafollicular cells (C cells) and typically shows nests or sheets of polygonal cells with abundant eosinophilic cytoplasm, and may show amyloid deposition. Option: D. Anaplastic carcinoma: It is a rare and aggressive thyroid malignancy characterized by the absence of differentiated thyroid markers and the presence of bizarre, pleomorphic giant cells with high mitotic activity.</p>\n<p><strong>Table:</strong></p><p>Types of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Histopathological findings of a thyroidectomy from an old patient with clinical presentation of a rapidly enlarging mass and symptoms of dyspnea, dysphagia, hoarseness, and cough are shown below. What is the likely diagnosis?", "options": [{"label": "A", "text": "Medullary carcinoma", "correct": false}, {"label": "B", "text": "Papillary carcinoma", "correct": false}, {"label": "C", "text": "Follicular carcinoma", "correct": false}, {"label": "D", "text": "Anaplastic carcinoma", "correct": true}], "correct_answer": "D. Anaplastic carcinoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161332436-QTDP163015IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Anaplastic carcinoma The given clinical scenario with a histopathological image showing spindle cells along with pleomorphic giant cells suggests the diagnosis of Anaplastic carcinoma. Anaplastic carcinoma is a highly aggressive and rare type of thyroid cancer, typically occurring in older patients.</p>\n<p><strong>Highyeild:</strong></p><p>Anaplastic thyroid carcinoma Aka undifferentiated carcinoma Seen in older patients: mean age of 65 years Associated with TP53 mutation Typically presents as a rapidly growing neck mass that may be associated with dysphagia, dyspnea, hoarseness , and other symptoms related to compression of nearby structures. Histological features: Presence of pleomorphic, spindle-shaped, or giant cells with bizarre nuclei. Tumour cells may also show abundant mitotic figures, areas of necrosis, and invasion into surrounding tissues. The tumour may be composed of spindle cells, epithelioid cells, or a combination of both. Poor prognosis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Medullary carcinoma: MTC of the thyroid typically shows nests or sheets of polygonal cells with abundant cytoplasm and amyloid deposits, rather than spindle cells and pleomorphic giant cells. Option: B . Papillary carcinoma: It typically shows branching papillae with fibrovascular cores and characteristic nuclear features such as orphan Annie eye nuclei and nuclear grooves, rather than spindle cells and pleomorphic giant cells. Option: C. Follicular carcinoma: It typically shows uniform follicles forming repetitive patterns with the invasion of the thyroid capsule and/or blood vessels, rather than spindle cells and pleomorphic giant cells.</p>\n<p><strong>Table:</strong></p><p>Types\n of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are features of medullary carcinoma except:", "options": [{"label": "A", "text": "It arises from parafollicular cells or C cells", "correct": false}, {"label": "B", "text": "It is associated with MEN 2A or 2B", "correct": false}, {"label": "C", "text": "RAS plays an important role in its genesis", "correct": true}, {"label": "D", "text": "It secret calcitonin", "correct": false}], "correct_answer": "C. RAS plays an important role in its genesis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>RAS plays an important role in its genesis RAS mutations are commonly seen in follicular thyroid carcinom a but not in MTC. Instead, mutations in the RET proto-oncogene are associated with the development of MTC. R ET mutations can occur sporadically or as part of an inherited syndrome such as MEN 2A or 2B.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option:A., B, D: All are true with respect to Medullary thyroid carcinoma.</p>\n<p><strong>Table:</strong></p><p>Common\n proto-oncogenes implicated in thyroid carcinoma: Thyroid carcinoma proto-oncogene Papillary RET (RET PTC translocation), NTRK1, BRAF, Follicular PAX8-PPARG, RAS Medullary RET (RET point mutation) Anaplastic TP53, BRAF, RAS Toxic adenoma GNAS mutation</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Identify the tumour based on the histological features from a thyroidectomy specimen. Which of the following is associated with this condition?", "options": [{"label": "A", "text": "Sipple syndrome", "correct": true}, {"label": "B", "text": "Cowden syndrome", "correct": false}, {"label": "C", "text": "HNPCC", "correct": false}, {"label": "D", "text": "Wermer syndrome", "correct": false}], "correct_answer": "A. Sipple syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Sipple syndrome The given histopathological image shows abundant extracellular material deposition w hich suggests the diagnosis of Medullary thyroid carcinoma. It is associated with sipple syndrome or MEN2A.</p>\n<p><strong>Highyeild:</strong></p><p>Medullary carcinoma Arises from parafollicular “C cells” which produce and secrete calcitonin, a hormone that regulates calcium metabolism. It can be sporadic or hereditary and is usually more aggressive than papillary or follicular carcinom Histology: Sheets of polygonal cells in amyloid stromatolites Associated with MEN2A and 2B (RET mutations) Immunohistochemistry: MTC cells typically stain positive for calcitonin, chromogranin, and synaptophysin. Calcitonin and serotonin secreted by MTC are responsible for diarrhoea</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B . Cowden syndrome: It is a rare genetic disorder that is associated with the development of benign and malignant tumours, including thyroid cancer, but it is not specifically associated with medullary carcinoma. Option: C. HNPCC: It (hereditary non-polyposis colorectal cancer) is a genetic disorder that increases the risk of developing colorectal cancer, but it is not associated with thyroid cancer. Option: D. Wermer syndrome: Also known as multiple endocrine neoplasia type 1 (MEN1), is a genetic disorder that is associated with the development of tumours in multiple endocrine organs, including the parathyroid glands, pancreas, and pituitary gland, but it is not specifically associated with thyroid cancer.</p>\n<p><strong>Extraedge:</strong></p><p>Multiple endocrine neoplasia</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Electron microscopy feature of medullary carcinoma of the thyroid is-", "options": [{"label": "A", "text": "Increased mitochondria", "correct": false}, {"label": "B", "text": "Presence of dense granules", "correct": true}, {"label": "C", "text": "Shrunken endoplasmic reticulum", "correct": false}, {"label": "D", "text": "Dilated Golgi apparatus", "correct": false}], "correct_answer": "B. Presence of dense granules", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Presence of dense granules Presence of dense granules is the electron microscopy feature of medullary carcinoma of the thyroid. Medullary carcinoma of the thyroid arises from the parafollicular cells (C-cells) which are responsible for producing calcitonin. The tumour cells of medullary carcinoma secrete calcitonin and other peptides such as carcinoembryonic antigen (CEA).</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Increased mitochondria: This is a non-specific finding and can be observed in various tumours and other conditions. It is not specific to medullary carcinoma of the thyroid. Option: C. Shrunken endoplasmic reticulum: This is an unusual finding and is not typically seen in medullary carcinoma of the thyroid. It can be observed in conditions such as ischemia, viral infections, and drug toxicity. Option: D. Dilated Golgi apparatus: This feature can be observed in many secretory cells and is not specific to medullary carcinoma of the thyroid.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the characteristic cytological findings in a 21-year-old patient who underwent FNAC identify the lesion:", "options": [{"label": "A", "text": "Follicular carcinoma", "correct": false}, {"label": "B", "text": "Medullary carcinoma", "correct": false}, {"label": "C", "text": "Anaplastic carcinoma", "correct": false}, {"label": "D", "text": "Papillary carcinoma", "correct": true}], "correct_answer": "D. Papillary carcinoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Papillary carcinoma The FNAC image shows Orphan Annie eye nucle i, which are nuclei that lack pigment and resemble an empty ocular socket and the Presence of enlarged, irregularly shaped, and overlapping nuclei with nuclear grooves and pseudo inclusion suggests the diagnosis of Papillary thyroid carcinoma.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Follicular carcinoma: The cytological features of follicular carcinoma usually include microfollicular pattern, scanty colloid, and uniform follicular cells arranged in sheets. Option: B. Medullary carcinoma: The cytological features of medullary carcinoma usually include spindle-shaped or polygonal cells with eccentric nuclei, amyloid deposits, and calcitonin positivity. Option: C. Anaplastic carcinoma: The cytological features of anaplastic carcinoma usually include pleomorphic, bizarre, and anaplastic cells, with abundant cytoplasm, and large nucleoli.</p>\n<p><strong>Table:</strong></p><p>Types\n of thyroid cancer and their histopathological findings</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most common cause of endogenous hyperthyroidism?", "options": [{"label": "A", "text": "Pituitary adenoma", "correct": false}, {"label": "B", "text": "Grave’s disease", "correct": true}, {"label": "C", "text": "Multinodular goitre", "correct": false}, {"label": "D", "text": "Adenomatoid goitre", "correct": false}], "correct_answer": "B. Grave’s disease", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Grave’s disease Grave’s disease is the most common cause of endogenous hyperthyroidism . It is an autoimmune disorder in which thyroid-stimulating immunoglobulin (TSI) antibodies bind to and activate the thyrotropin receptor on thyroid cells, resulting in excess production of thyroid hormone.</p>\n<p><strong>Highyeild:</strong></p><p>Grave’s disease Most common cause of hyperthyroidism Autoimmune disorder, type II hypersensitivity Thyroid-stimulating immunoglobulin (TSI) antibodies bind to and activate the thyrotropin receptor on thyroid cells, resulting in excess production of thyroid hormone. Features: Diffuse goitre Hyperthyroidism signs and symptoms: weight loss, heat intolerance, tremors, palpitations, and anxiety Ophthalmopathy ( Graves' ophthalmopathy ) with symptoms such as proptosis, diplopia, and eye irritation Dermopathy ( Graves' dermopathy ) is characterized by the thickening of the skin on the shins and feet Histological findings: Tall, crowded follicular epithelial cells Scalloped colloid</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Pituitary adenoma: This is a cause of endogenous hypersecretion of thyroid hormone, but it leads to secondary hyperthyroidism rather than primary hyperthyroidism, as the excess secretion is due to the adenoma secreting excessive TSH which stimulates the thyroid gland to produce more thyroid hormone. Option: C. Multinodular goitre: Multinodular goitre can cause hyperthyroidism due to the autonomous production of thyroid hormones by the nodules. However, it is not the most common cause of hyperthyroidism. Option: D. Adenomatoid goitre: Adenomatoid goitre is a type of nodular goitre, but it is not a common cause of hyperthyroidism. Like multinodular goitre, it can cause hyperthyroidism due to the autonomous production of thyroid hormone by the adenoma, but this is not the most common cause of hyperthyroidism.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Based on the histological features as shown in the diagram identify the thyroid lesion:", "options": [{"label": "A", "text": "Thyroid adenoma", "correct": false}, {"label": "B", "text": "Hashimoto thyroiditis", "correct": false}, {"label": "C", "text": "Goiter", "correct": true}, {"label": "D", "text": "Follicular carcinoma", "correct": false}], "correct_answer": "C. Goiter", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689161336313-QTDP163024IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Goiter The given histopathological image showing distended follicles and colloid-rich glands suggests the diagnosis of Goitre.</p>\n<p><strong>Highyeild:</strong></p><p>Causes of Goitre Smooth/diffuse goitre Nodular ● Grave’s disease ● Hashimoto thyroiditis ● Iodine deficiency ● TSH-Secreting pituitary adenoma ● Toxic multinodular goitre ● Thyroid adenoma ● Thyroid cancer ● Thyroid cysts</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Thyroid adenoma: These are solitary, well-circumscribed lesions that may exhibit different histological patterns, including follicular or papillary, but they do not typically show a diffuse glandular enlargement. Option: B. Hashimoto thyroiditis: It is an autoimmune disorder that causes inflammation of the thyroid gland, which may destroy follicles and replacement by lymphocytes. Option: D. Follicular carcinoma: The histological features of follicular carcinoma include uniform follicular cells forming repetitive follicular patterns and invasion of the thyroid capsule and/or vasculature.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 31 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following are conditions where the Mantoux test can be false negative except:", "options": [{"label": "A", "text": "Sarcoidosis", "correct": false}, {"label": "B", "text": "Malnutrition", "correct": false}, {"label": "C", "text": "Hodgkin lymphoma", "correct": false}, {"label": "D", "text": "Prior vaccination by BCG", "correct": true}], "correct_answer": "D. Prior vaccination by BCG", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Prior vaccination by BCG Shows False Positive result .</p>\n<p><strong>Highyeild:</strong></p><p>Tuberculin/Mantoux Test The tuberculin skin test is performed by intracutaneous injection of purified protein derivative of M. tuberculosis induces a visible and palpable induration that peaks in 48 to 72 hours . A positive tuberculin test signifies T-cell–mediated immunity to mycobacterial antigens but does not differentiate between infection and active disease . Mantoux/Tuberculin test is Type IV Hypersensitivity . True Negative: A person has never been infected with TB. True Positive: The person has developed antibodies against TB. False-negative reactions may occur in the setting of certain viral infections, sarcoidosis, malnutrition, Hodgkin lymphoma, immunosuppression , and (notably) overwhelming active tuberculous disease . False-positive reactions may result from infection by atypical mycobacteria or prior vaccination with BCG (Bacillus Calmette-Guerin) , an attenuated strain of M. bovis that is used as a vaccine in some countries.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Sarcoidosis. Shows False-negative result . Option: B. Malnutrition. Shows False-negative result . Option: C. Hodgkin lymphoma. Shows False-negative result .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which mediator plays an important role in TH1-mediated macrophage activation and killing of bacteria?", "options": [{"label": "A", "text": "TNF", "correct": false}, {"label": "B", "text": "IL 2", "correct": false}, {"label": "C", "text": "IFN-γ", "correct": true}, {"label": "D", "text": "TGF beta", "correct": false}], "correct_answer": "C. IFN-γ", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IFN-γ TH1-mediated macrophage activation and killing of bacteria: TH1 cells , both in lymph nodes and in the lung, produce IFN-γ . IFN-γ is the critical mediator that enables macrophages to contain the M. tuberculosis infection . First, IFN-γ stimulates maturation of the phagolysosome in infected macrophages , exposing the bacteria to a lethal acidic, oxidizing environment. Second, IFN-γ stimulates the expression of inducible nitric oxide (NO) synthase , which produces NO . NO combines with other oxidants to create reactive nitrogen intermediates, which are important for killing mycobacteria . Third, IFN-γ mobilizes antimicrobial peptides ( defensins ) against the bacteria. Finally, IFN-γ stimulates autophagy , which sequesters and then destroys damaged organelles and intracellular bacteria such as M. tuberculosis. In addition to stimulating macrophages to kill mycobacteria, the Th1 response orchestrates the formation of granulomas and caseous necrosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. TNF. Incorrect . Option: B. IL 2. Incorrect . Option: D. TGF beta. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Macrophages activated by IFN-γ differentiate into the “ epithelioid histiocytes ” that aggregate to form granulomas ; some epithelioid cells may fuse to form giant cells .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Ghon complex is", "options": [{"label": "A", "text": "Parenchymal lung lesion", "correct": false}, {"label": "B", "text": "Lymph nodal involvement", "correct": false}, {"label": "C", "text": "Calcified lesion", "correct": false}, {"label": "D", "text": "A and B", "correct": true}], "correct_answer": "D. A and B", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>A and B The combination of parenchymal lung lesion and nodal involvement is referred to as the Ghon complex .</p>\n<p><strong>Highyeild:</strong></p><p>Ghon’s complex Typically, the inhaled bacilli implant in the distal airspaces of the lower part of the upper lobe or the upper part of the lower lobe , usually close to the pleura . As sensitization develops, a 1- to 1.5-cm area of gray-white inflammation with consolidation emerges , known as the Ghon focus . In most cases, the center of this focus undergoes caseous necrosis . Tubercle bacilli, free or within phagocytes, drain to the regional nodes, which are often caseate. The combination of parenchymal lung lesion and nodal involvement is referred to as the Ghon complex .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Parenchymal lung lesion. Called Ghon focus . Option: B. Lymph nodal involvement. Incorrect . Option: C. Calcified lesion. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In primary tuberculosis, all of the following can be seen except:", "options": [{"label": "A", "text": "Caseation", "correct": false}, {"label": "B", "text": "Cavitation", "correct": true}, {"label": "C", "text": "Calcification", "correct": false}, {"label": "D", "text": "Langerhans giant cell", "correct": false}], "correct_answer": "B. Cavitation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cavitation</p>\n<p><strong>Highyeild:</strong></p><p>Primary tuberculosis is a form of the disease that develops in a previously unexposed and therefore unsensitized person . With primary tuberculosis, the source of the organism is exogenous . In most people, the primary infection is contained, but in others, primary tuberculosis is progressive. In contrast to secondary tuberculosis (an apical disease with cavitation; see later), progressive primary tuberculosis more often resembles acute bacterial pneumonia with the consolidation of the lobe, hilar adenopathy, and pleural effusion. Lymphatic and hematogenous dissemination following primary infection may result in the development of tuberculous meningitis and miliary tuberculosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Caseation. Seen in primary TB . Option: C. Calcification. Seen in primary TB . Option: D. Langerhans giant cell. Seen in primary TB .</p>\n<p><strong>Extraedge:</strong></p><p>Secondary pulmonary tuberculosis classically involves the apex of the upper lobes of one or both lungs . Because of the preexistence of hypersensitivity, the bacilli elicit a prompt and marked tissue response that tends to wall off the focus of infection . As a result, the regional lymph nodes are less prominently involved early in secondary disease than they are in primary tuberculosis. On the other hand, cavitation occurs readily in the secondary form . Indeed, cavitation is almost inevitable in neglected secondary tuberculosis , and erosion of the cavities into an airway is an important source of infection because the person now coughs sputum that contains bacteria .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Lung biopsy from a 25-year-old patient who presented with a history of weight loss, evening rise of temperature, raised ESR, and cervical lymphadenopathy. Based on clinical findings and the histological diagram given below, what is your diagnosis?", "options": [{"label": "A", "text": "Hodgkin lymphoma", "correct": false}, {"label": "B", "text": "Tuberculosis", "correct": true}, {"label": "C", "text": "Asthma", "correct": false}, {"label": "D", "text": "Squamous cell carcinoma", "correct": false}], "correct_answer": "B. Tuberculosis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686826656223-QTDP066006IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Tuberculosis</p>\n<p><strong>Highyeild:</strong></p><p>Histologically , sites of active involvement are marked by a characteristic granulomatous inflammatory reaction that forms both caseating and noncaseating tubercles . Individual tubercles are microscopic; it is only when multiple granulomas coalesce that they become macroscopically visible. The granulomas are usually enclosed within a fibroblastic rim punctuated by lymphocytes . Multinucleated giant cells are present in the granulomas. Immunocompromised people do not form the characteristic granulomas, and their macrophages contain many bacilli</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Hodgkin lymphoma. Hodgkin’s Lymphoma is B cell-derived lymphoma . Reed–Sternberg cells are distinctive, giant cells found with light microscopy in biopsies from individuals with Hodgkin lymphoma. Option: C. Asthma is a reversible bronchospasm, Type I Hypersensitivity, microscopy shows Curshman spirals, Creola bodies, and Charcot Leyden crystals ( made up of Galactin 10) . Option: D. Squamous cell carcinoma. Squamous Cell Carcinoma microscopically shows Dysplastic squamous epithelium, Tumor nests in subepithelium, and Keratin pearls .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding mycobacterium avium complex except:", "options": [{"label": "A", "text": "Infection is seen predominantly in immunocompromised patients", "correct": false}, {"label": "B", "text": "Hallmark of disease is macrophages laden with acid-fast bacilli", "correct": false}, {"label": "C", "text": "Grossly, the involved organ shows yellow pigmentation", "correct": false}, {"label": "D", "text": "Numerous granuloma formation is always seen", "correct": true}], "correct_answer": "D. Numerous granuloma formation is always seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Numerous granuloma formation is always seen</p>\n<p><strong>Highyeild:</strong></p><p>Mycobacterium avium complex (MAC): Clinically significant infection with Mycobacterium avium complex (MAC) is uncommon except among people with T-cell immunodeficiency due to AIDS , and immunosuppression resulting from treatment for transplant rejection or autoimmune diseases . Normal host defense mechanisms usually prevent infection, so vulnerable individuals include those with structural lung damage, cystic fibrosis, bronchiectasis, primary ciliary dyskinesia, chronic obstructive pulmonary disease, or pneumoconiosis . The hallmark of MAC infections in patients with HIV is abundant acid-fast bacilli within macrophages. Depending on the severity of immunodeficiency , MAC infections can be widely disseminated throughout the mononuclear phagocyte system , causing enlargement of involved lymph nodes, liver, and spleen , or localized to the lungs. There may be a yellowish pigmentation to these organs secondary to a large number of organisms present in swollen macrophages . Granulomas, lymphocytes, and tissue destruction are RARE . Mycobacterium avium infection in a patient with AIDS, showing massive infection with acid-fast organisms. This pattern is more common in patients with acquired immunodeficiencies.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Infection is seen predominantly in immunocompromised patients. Correct . Option: B. Hallmark of the disease is macrophages laden with acid-fast bacilli. Correct . Option: C. Grossly, the involved organ shows yellow pigmentation. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 16 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The most common primary cardiac tumor is-", "options": [{"label": "A", "text": "Fibroma", "correct": false}, {"label": "B", "text": "Lipoma", "correct": false}, {"label": "C", "text": "Myxoma", "correct": true}, {"label": "D", "text": "Rhabdomyoma", "correct": false}], "correct_answer": "C. Myxoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myxoma Primary cardiac tumors are uncommon; moreover, most are benign . In descending order of frequency (combined pediatric and adult populations), these are myxomas , fibromas , lipomas , papillary fibroelastosis , and rhabdomyoma .</p>\n<p><strong>Highyeild:</strong></p><p>Myxomas: Myxomas are the most common primary tumor of the adult heart . These are benign neoplasms arising from primitive multipotent mesenchymal cells. Familial syndromes associated with myxomas have activating mutations in the GNAS1 gene , encoding a subunit of G protein (Gsα) (in association with McCune-Albright syndrome ) or null mutations in PRKAR1A , encoding a regulatory subunit of a cyclic-AMP–dependent protein kinase ( Carney complex ). About 90% of myxomas arise in the atria , with a left-to-right ratio of approximately 4:1 . Atrial myxoma. (A) A large sessile lesion arises from the region of the fossa ovalis and extends into the mitral valve orifice. (B) Abundant amorphous extracellular matrix contains scattered multinucleate myxoma cells (arrowheads) in various groupings, including abnormal vessel-like formations (arrow). Usually single , but can rarely be multiple. The region of the fossa ovalis in the atrial septum is the favored site of origin . Can be sessile or pedunculated lesions. They vary from globular hard masses mottled with hemorrhage to soft, translucent, papillary, or villous lesions having a gelatinous appearance . The pedunculated form is often sufficiently mobile to move during systole into the atrioventricular valve opening , causing an intermittent obstruction that may be position-dependent . Histologically, myxomas are composed of stellate or globular myxoma cells embedded within an abundant acid mucopolysaccharide ground substance . Peculiar vessel-like or glandlike structures are characteristic. Hemorrhage and mononuclear inflammation are usually present . The major clinical manifestations are due to valvular “ball-valve” obstruction , embolization , or a syndrome of constitutional symptoms, such as fever and malaise.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Fibroma. Incorrect . Option: B. Lipoma. Incorrect . Option: D. Rhabdomyoma. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Sometimes fragmentation and systemic embolization can be seen. Constitutional symptoms are probably due to the elaboration by some myxomas of the cytokine interleukin-6 , a major mediator of the acute-phase response. Echocardiography provides the opportunity to identify these masses noninvasively. Surgical removal is usually curative ; rarely, presumably with incomplete excision, the neoplasm can recur months to years later.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding myxoma of the heart except:", "options": [{"label": "A", "text": "It is a benign neoplasm", "correct": false}, {"label": "B", "text": "It arises from multipotent mesenchymal cells", "correct": false}, {"label": "C", "text": "90% of cases occur in the ventricle", "correct": true}, {"label": "D", "text": "Familial syndromes are associated with a mutation in GNAS 1 and PRKAR1A genes", "correct": false}], "correct_answer": "C. 90% of cases occur in the ventricle", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>90% of cases occur in the ventricle False , 90% of myxomas arise in the atria , with a left-to-right ratio of approximately 4:1 .</p>\n<p><strong>Highyeild:</strong></p><p>Myxomas: Myxomas are the most common primary tumor of the adult heart . These are benign neoplasms arising from primitive multipotent mesenchymal cells. Familial syndromes associated with myxomas have activating mutations in the GNAS1 gene , encoding a subunit of G protein (Gsα) (in association with McCune-Albright syndrome ) or null mutations in PRKAR1A , encoding a regulatory subunit of a cyclic-AMP–dependent protein kinase ( Carney complex ). About 90% of myxomas arise in the atria , with a left-to-right ratio of approximately 4:1 . Atrial myxoma. (A) A large sessile lesion arises from the region of the fossa ovalis and extends into the mitral valve orifice. (B) Abundant amorphous extracellular matrix contains scattered multinucleate myxoma cells (arrowheads) in various groupings, including abnormal vessel-like formations (arrow). Usually single , but can rarely be multiple. The region of the fossa ovalis in the atrial septum is the favored site of origin . Can be sessile or pedunculated lesions. They vary from globular hard masses mottled with hemorrhage to soft, translucent, papillary, or villous lesions having a gelatinous appearance . The pedunculated form is often sufficiently mobile to move during systole into the atrioventricular valve opening , causing an intermittent obstruction that may be position-dependent . Histologically, myxomas are composed of stellate or globular myxoma cells embedded within an abundant acid mucopolysaccharide ground substance . Peculiar vessel-like or glandlike structures are characteristic. Hemorrhage and mononuclear inflammation are usually present . The major clinical manifestations are due to valvular “ball-valve” obstruction , embolization , or a syndrome of constitutional symptoms, such as fever and malaise.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is a benign neoplasm. Correct . Option: B. It arises from multipotent mesenchymal cells. Correct . Option: D. Familial syndromes are associated with a mutation in GNAS 1 and PRKAR1A genes. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Sometimes fragmentation and systemic embolization can be seen. Constitutional symptoms are probably due to the elaboration by some myxomas of the cytokine interleukin-6 , a major mediator of the acute-phase response. Echocardiography provides the opportunity to identify these masses noninvasively. Surgical removal is usually curative ; rarely, presumably with incomplete excision, the neoplasm can recur months to years later.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the morphology of myxoma of the heart except:", "options": [{"label": "A", "text": "Fossa ovalis in the atrial septum is the favored site of origin", "correct": false}, {"label": "B", "text": "Myxomas are the most common primary tumor of the adult heart", "correct": false}, {"label": "C", "text": "Histologically, myxomas are composed of stellate or globular myxoma cells embedded within an abundant acid mucopolysaccharide ground substance", "correct": false}, {"label": "D", "text": "Haemorrhage and inflammation are characteristically absent", "correct": true}], "correct_answer": "D. Haemorrhage and inflammation are characteristically absent", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Haemorrhage and inflammation are characteristically absent. False , Hemorrhage, and mononuclear inflammation are usually present .</p>\n<p><strong>Highyeild:</strong></p><p>Myxomas: Myxomas are the most common primary tumor of the adult heart . These are benign neoplasms arising from primitive multipotent mesenchymal cells. Familial syndromes associated with myxomas have activating mutations in the GNAS1 gene , encoding a subunit of G protein (Gsα) (in association with McCune-Albright syndrome ) or null mutations in PRKAR1A , encoding a regulatory subunit of a cyclic-AMP–dependent protein kinase ( Carney complex ). About 90% of myxomas arise in the atria , with a left-to-right ratio of approximately 4:1 . Atrial myxoma. (A) A large sessile lesion arises from the region of the fossa ovalis and extends into the mitral valve orifice. (B) Abundant amorphous extracellular matrix contains scattered multinucleate myxoma cells (arrowheads) in various groupings, including abnormal vessel-like formations (arrow). Usually single , but can rarely be multiple. The region of the fossa ovalis in the atrial septum is the favored site of origin . Can be sessile or pedunculated lesions. They vary from globular hard masses mottled with hemorrhage to soft, translucent, papillary, or villous lesions having a gelatinous appearance . The pedunculated form is often sufficiently mobile to move during systole into the atrioventricular valve opening , causing an intermittent obstruction that may be position-dependent . Histologically, myxomas are composed of stellate or globular myxoma cells embedded within an abundant acid mucopolysaccharide ground substance . Peculiar vessel-like or glandlike structures are characteristic. Hemorrhage and mononuclear inflammation are usually present . The major clinical manifestations are due to valvular “ball-valve” obstruction , embolization , or a syndrome of constitutional symptoms, such as fever and malaise.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is a benign neoplasm. Correct . Option: B. It arises from multipotent mesenchymal cells. Correct . Option: D. Familial syndromes are associated with a mutation in GNAS 1 and PRKAR1A genes. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Sometimes fragmentation and systemic embolization can be seen. Constitutional symptoms are probably due to the elaboration by some myxomas of the cytokine interleukin-6 , a major mediator of the acute-phase response. Echocardiography provides the opportunity to identify these masses noninvasively. Surgical removal is usually curative ; rarely, presumably with incomplete excision, the neoplasm can recur months to years later.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "In a patient diagnosed with McCune Albright syndrome, ECHO showed a mass causing ball-valve obstruction of the mitral valve orifice. Biopsy from the mass is given below, what is your diagnosis?", "options": [{"label": "A", "text": "Lipoma", "correct": false}, {"label": "B", "text": "Myxoma", "correct": true}, {"label": "C", "text": "Rhabdomyoma", "correct": false}, {"label": "D", "text": "Fibroelastoma", "correct": false}], "correct_answer": "B. Myxoma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1689155852771-QTDP099004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Myxoma The patient is diagnosed with McCune Albright syndrome , and ECHO shows a mass causing ball-valve obstruction of the mitral valve orifice (i.e. mass arising from left atria) is suggestive of Myxoma . The biopsy shows myxoma cells embedded within an abundant acid mucopolysaccharide ground substance which again is highly suggestive of Myxoma .</p>\n<p><strong>Highyeild:</strong></p><p>Myxomas: Myxomas are the most common primary tumor of the adult heart . These are benign neoplasms arising from primitive multipotent mesenchymal cells. Familial syndromes associated with myxomas have activating mutations in the GNAS1 gene , encoding a subunit of G protein (Gsα) (in association with McCune-Albright syndrome ) or null mutations in PRKAR1A , encoding a regulatory subunit of a cyclic-AMP–dependent protein kinase ( Carney complex ). About 90% of myxomas arise in the atria , with a left-to-right ratio of approximately 4:1 . Atrial myxoma. (A) A large sessile lesion arises from the region of the fossa ovalis and extends into the mitral valve orifice. (B) Abundant amorphous extracellular matrix contains scattered multinucleate myxoma cells (arrowheads) in various groupings, including abnormal vessel-like formations (arrow). Usually single , but can rarely be multiple. The region of the fossa ovalis in the atrial septum is the favored site of origin . Can be sessile or pedunculated lesions. They vary from globular hard masses mottled with hemorrhage to soft, translucent, papillary, or villous lesions having a gelatinous appearance . The pedunculated form is often sufficiently mobile to move during systole into the atrioventricular valve opening , causing an intermittent obstruction that may be position-dependent . Histologically, myxomas are composed of stellate or globular myxoma cells embedded within an abundant acid mucopolysaccharide ground substance . Peculiar vessel-like or glandlike structures are characteristic. Hemorrhage and mononuclear inflammation are usually present . The major clinical manifestations are due to valvular “ball-valve” obstruction , embolization , or a syndrome of constitutional symptoms, such as fever and malaise.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Lipoma. Incorrect , the conventional lipoma is a well-encapsulated mass of mature adipocytes . The fat contains a few small capillaries within thin fibrous strands . A thin fibrous capsule is often seen. Fat necrosis and other inflammatory changes may be seen when lipomas are traumatized. Option: C. Rhabdomyoma. Incorrect , Rhabdomyomas are gray-white myocardial masses that can be small or up to several centimeters in diameter. They are usually multiple and involve the ventricles preferentially. Microscopically, they are composed of bizarre, markedly enlarged myocytes with large collections of glycogen . Routine histologic processing removes the glycogen and artifactually reduces the abundant cytoplasm to thin strands that stretch from the nucleus to the surface membrane, an appearance referred to as “spider” cells . Option: D. Fibroelastoma. Incorrect , located on valves , particularly the ventricular surfaces of semilunar valves and the atrial surfaces of atrioventricular valves . Histologically, the projections are covered by a surface endothelium surrounding a core of myxoid connective tissue with abundant mucopolysaccharide matrix and elastic fibers.</p>\n<p><strong>Extraedge:</strong></p><p>Sometimes fragmentation and systemic embolization can be seen. Constitutional symptoms are probably due to the elaboration by some myxomas of the cytokine interleukin-6 , a major mediator of the acute-phase response. Echocardiography provides the opportunity to identify these masses noninvasively. Surgical removal is usually curative ; rarely, presumably with incomplete excision, the neoplasm can recur months to years later.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 14 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Sideroblastic anemia is seen in chronic poisoning of", "options": [{"label": "A", "text": "Lead", "correct": true}, {"label": "B", "text": "Arsenic", "correct": false}, {"label": "C", "text": "Copper", "correct": false}, {"label": "D", "text": "Mercury", "correct": false}], "correct_answer": "A. Lead", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lead</p>\n<p><strong>Highyeild:</strong></p><p>Sideroblastic anemia occurs due to abnormal utilization of iron during erythropoiesis ie iron overloading type of presentation with Microcytic anemia & all lab findings are opposite to that of Iron Deficiency Anemia . Ring sideroblasts are seen in Bone Marrow . Treatment: Pyridoxine (Vit B6), as it is a cofactor for ALA synthase .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Options: B, C & D are False .</p>\n<p><strong>Extraedge:</strong></p><p>Sideroblastic anemia is seen in: Lead poisoning Myelodysplastic syndrome Drugs ( isoniazid , pyrazinamide, chloramphenicol) Alcoholism Copper deficiency (zinc ingestion, copper chelation, nutritional, malabsorption) Hypothermia Ring sideroblasts with Prussian blue stain</p>\n<p><strong>Table:</strong></p><p>Features of Lead poisoning: Children absorb more\n ingested lead than adults; the main source of exposure for children is lead-containing\n paint in older housing and lead-containing drinking water . Excess lead causes CNS\n defects in children and peripheral neuropathy in adults . It\n also interferes with the remodeling of cartilage and causes anemia by\n interfering with hemoglobin synthesis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What type of RBCs are seen in chronic renal failure?", "options": [{"label": "A", "text": "Microcytic", "correct": false}, {"label": "B", "text": "Macrocytic", "correct": false}, {"label": "C", "text": "Normocytic", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Normocytic", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Normocytic Normocytic normochromic RBCs are seen in chronic renal failure . The erythrocytes usually are normocytic and normochromic, but slight macrocytosis is occasionally observed . The majority of red cells appear normal on blood smears. Occasionally, however, “burr” cells are observed along with some triangular, helmet-shaped, or fragmented cells.</p>\n<p><strong>Highyeild:</strong></p><p>Anemia in CKD: The basis of anemia in renal failure is multifactorial, but the dominant cause is the diminished synthesis of erythropoietin (EPO) by the damaged kidneys, leading to inadequate red cell production . Uremia also reduces red cell lifespan and impairs platelet function (both through uncertain mechanisms), and these effects may also contribute to anemia through extravascular hemolysis, abnormal bleeding, and eventually iron deficiency .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Options: A, B & D are False .</p>\n<p><strong>Extraedge:</strong></p><p>Treatment: Administration of recombinant erythropoietin and iron replacement therapy significantly improves anemia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Macrocytosis in CBC can be diagnosed by-", "options": [{"label": "A", "text": "Decreased MCV", "correct": false}, {"label": "B", "text": "Decreased MCHC", "correct": false}, {"label": "C", "text": "Increased MCV", "correct": true}, {"label": "D", "text": "Decreased MCH", "correct": false}], "correct_answer": "C. Increased MCV", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Increased MCV Macrocytosis is usually seen in Megaloblastic Anemia , so in CBC it can be diagnosed by decreased Hematocrit (due to decreased RBC mass in Anemia) & Increased MCV (due to increased size of RBCs)</p>\n<p><strong>Highyeild:</strong></p><p>Investigation of macrocytic anemia: Investigation of a macrocytic anaemia. MDS, myelo- dysplastic syndrome. A high MCV with oval macrocytes and hypersegmented neutrophils suggests folate or cobalamin deficiency and is an indication for assays of these vitamins. Plasma methylmalonic acid assays may be a useful second-line test to help clarify uncertainties of underlying biochemical or functional cobalamin deficiencies. Megaloblastic anemia. A peripheral blood smear shows a hypersegmented neutrophil with a six-lobed nucleus. (Courtesy Dr. Robert W. McKenna, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.) As there is no definitive test to define cobalamin deficiency, treatment should be started if there is a strong clinical suspicion of deficiency irrespective of the test results to avoid neurological impairment .</p>\n<p><strong>Extraedge:</strong></p><p>In the absence of intrinsic factor antibodies, the diagnosis of pernicious anemia may be presumptive. Pernicious anemia is commonly associated with autoimmune thyroid disease and other autoimmune disorders, such as diabetes mellitus. A high MCV may also be the result of alcohol excess and liver disease or the use of drugs such as hydroxycarbamide .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Bite cells are characteristic of:", "options": [{"label": "A", "text": "G6PD deficiency", "correct": true}, {"label": "B", "text": "Thalassemia", "correct": false}, {"label": "C", "text": "Hereditary spherocytosis", "correct": false}, {"label": "D", "text": "Sideroblastic anemia", "correct": false}], "correct_answer": "A. G6PD deficiency", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>G6PD deficiency Bite cells are characteristic of G6PD deficiency.</p>\n<p><strong>Highyeild:</strong></p><p>G6PD deficiency Abnormalities in the hexose monophosphate (HMP) shunt or glutathione metabolism resulting from deficient or impaired enzyme function reduce the ability of red cells to protect themselves against oxidative injuries and lead to hemolysis . G6PD deficiency is a recessive X-linked trait, placing males at much higher risk for symptomatic disease . G6PD mutations cause protein misfolding and breakdown , making it easier for red blood cells to break. As red blood cells age , the G6PD variants become less effective at protecting against oxidative stress , making older cells more likely to break than younger ones. The episodic hemolysis that is characteristic of G6PD deficiency is caused by exposures that generate oxidant stress. The most common triggers are infections, drugs implicated are numerous, including antimalarials (e.g., primaquine and chloroquine), sulfonamides, nitrofurantoin , and others. The most frequently cited food is the fava bean, which generates oxidants when metabolized called “Favism” . When G6PD deficient RBCs are exposed to high levels of oxidants , reactive sulfhydryl groups on globin chains cross-link and form Heinz bodies , and dark inclusions are seen in stained red blood cells. These Heinz bodies can damage the red blood cell membrane and cause intravascular hemolysis or reduced red blood cell flexibility . As the damaged cells pass through the spleen , macrophages remove the Heinz bodies , resulting in some cells retaining a ‘bitten’ appearance or becoming spherocytes due to loss of membrane surface area . Both types of damaged cells are then removed by phagocytes. Glucose-6-phosphate dehydrogenase deficiency: effects of oxidant drug exposure (peripheral blood smear). Inset, Red cells with precipitates of denatured globin (Heinz bodies) revealed by supravital staining. As the splenic macrophages pluck out these inclusions, \"bite cells\" like the one in this smear are produced. (Courtesy Dr. Robert W. McKenna, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Thalassemia. False . Option: C. Hereditary spherocytosis. False . Option: D. Sideroblastic anemia. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False about sickle cell anemia is:", "options": [{"label": "A", "text": "Splenomegaly is seen in the initial stage of sickle cell", "correct": false}, {"label": "B", "text": "Splenectomy is often needed", "correct": true}, {"label": "C", "text": "Sickling can be reversible and irreversible", "correct": false}, {"label": "D", "text": "The high prevalence of sickle cell trait in certain African populations stems from its protective effects against falciparum malaria", "correct": false}], "correct_answer": "B. Splenectomy is often needed", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Splenectomy is often needed Splenectomy, or removal of the spleen , can be beneficial in certain cases of sickle cell anemia, particularly if the spleen is enlarged and causing complications. With time, however, chronic erythrocytosis leads to splenic infarction, fibrosis, and progressive shrinkage, so that by adolescence or early adulthood only a small nubbin of fibrous splenic tissue is left, a process called auto splenectomy . Thus splenectomy is often not required .</p>\n<p><strong>Highyeild:</strong></p><p>Sickle cell anemia is a common hereditary hemoglobinopathy caused by a point mutation in β-globin that promotes polymerization of deoxygenated hemoglobin , leading to red cell distortion, hemolytic anemia, microvascular obstruction, and ischemic tissue damage. A point mutation in the 6th codon of β-globin leads to the replacement of glutamate by valine residue . It is characterized by the production of abnormal hemoglobin molecules . Hemoglobin A2 (HbA2) is a normal variant of hemoglobin that is increased in individuals with sickle cell anemia . The increased production of HbA2 is a compensatory mechanism to counterbalance the abnormal hemoglobin produced in sickle cell anemia (HbS) . table,tr,th,td {border:1px solid black;} MCV % S % A % A2 % F AS N 35-38 62-65 >3.5 <1 SS N 88-93 0 >3.5 5-10 S/ thalassaemia L 88-93 0 >3.5 5-10 Pathophysiology of sickle cell disease. HbA, Hemoglobin A; HbS, hemoglobin S; RBC, red blood cell. C/F: Dactylitis Acute chest syndrome Osteomyelitis( Salmonella typhi ) Stroke Retinopathy Papillary necrosis of the kidney Leg ulcers (due to vascular stagnation) Late changes: Reversible sickling leading to Hemolytic anemia Autosplenectomy</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Splenomegaly is seen in the initial stage of sickle cell, is true because splenomegaly, or enlargement of the spleen , is commonly seen in the initial stages of sickle cell anemia. Option: C. Sickling can be reversible and irreversible, which is true because sickling in sickle cell anemia is a reversible process that occurs in response to low oxygen levels in the blood. However, repeated episodes of sickling and unsickling can cause damage to the red blood cells and lead to irreversibly sickled cells. Option: D. The high prevalence of sickle cell trait in certain African populations stems from its protective effects against falciparum malaria, this is true because sickle cell trait, which is a carrier state for the sickle cell gene, is more common in certain African populations due to its protective effects against falciparum malaria . Individuals with sickle cell trait have a reduced risk of developing severe malaria because the sickle-shaped red blood cells are less hospitable to the malaria parasite.</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis: Reticulocytosis Sickling Test (Na Metabisulphite) Hb Electrophoresis Hb HPLC</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Hemoglobin H disease is caused by the deletion of-", "options": [{"label": "A", "text": "Single α-globin chain", "correct": false}, {"label": "B", "text": "Two α-globin chains", "correct": false}, {"label": "C", "text": "Three α-globin chains", "correct": true}, {"label": "D", "text": "All α-globin chains", "correct": false}], "correct_answer": "C. Three α-globin chains", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Three α-globin chains</p>\n<p><strong>Highyeild:</strong></p><p>Thalassemia is a genetically heterogeneous disorder caused by germline mutations that decrease the synthesis of either α-globin or β-globin, leading to anemia, tissue hypoxia, and red cell hemolysis related to the imbalance in globin chain synthesis. β-thalassemia is caused by deficient synthesis of β chains , whereas α-thalassemia is caused by deficient synthesis of α chains . Normal individuals have four α-globin genes, and the severity of α-thalassemia depends on how many α-globin genes are affected. In newborns with α-thalassemia, excess unpaired γ-globin chains form γ 4 tetramers known as hemoglobin Barts , whereas in older children and adults excess β-globin chains form β 4 tetramers known as HbH . Because free β and γ chains are more soluble than free α chains and form fairly stable homotetramers, hemolysis, and ineffective erythropoiesis are less severe than in β-thalassemia . Classification of α--thalassemia: table,tr,th,td {border:1px solid black;} a-thalassemia Genotype 1 gene deletion trait -, a/a,a Q 2 gene deletion trait -a/-a; homozygous a-thal trait --/;a,aheterozygous a -thal trait 3 gene deletion (HbH ) Q -,-/-,α 4 gene deletion (Hb- BART) Q -,-/-,-</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Single α-globin chain. Silent carrier , asymptomatic, and no red cell abnormality. Option: B. Two α-globin chains. α Thalassemia trait , asymptomatic like beta Thalassemia minor. Option: D. All α-globin chains. Hydrops fetalis , lethal in utero without transfusions.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Thalassemia major manifests in-", "options": [{"label": "A", "text": "Childhood", "correct": true}, {"label": "B", "text": "Puberty", "correct": false}, {"label": "C", "text": "Adolescence", "correct": false}, {"label": "D", "text": "Middle age", "correct": false}], "correct_answer": "A. Childhood", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Childhood β -Thalassemias: Clinical classification Manifestations Globin genotype (normal- β/β ) Thalassemia trait (minor) Asymptomatic May have mild anemia β/β0 β/β+ Thalassemia intermedia Mild to moderate anemia Variable need of blood transfusions +β+/β Q Thalassemia major Severe anemia & Jaundice Presents in childhood Requires multiple transfusion Hemolytic facies Hepatosplenomegaly +β+/β β+/β 0 β 0 /β 0 Q</p>\n<p><strong>Highyeild:</strong></p><p>Thalassemia is a genetically heterogeneous disorder caused by germline mutations that decrease the synthesis of either α-globin or β-globin, leading to anemia, tissue hypoxia, and red cell hemolysis related to the imbalance in globin chain synthesis. β-thalassemia is caused by deficient synthesis of β chains , whereas α-thalassemia is caused by deficient synthesis of α chains . Impaired β-globin synthesis results in anemia by two mechanisms. The deficit in HbA synthesis produces “underhemoglobinized” hypochromic, microcytic red cells with subnormal oxygen transport capacity. Even more important is the diminished survival of red cells and their precursors , which results from the imbalance in α- and β-globin synthesis. Unpaired α chains precipitate within red cell precursors, forming insoluble inclusions . These inclusions cause a variety of untoward effects, but membrane damage is the proximal cause of most red cell pathology. In severe β-thalassemia , ineffective red blood cell production leads to various issues. The excessive demand for red blood cells results in the overgrowth of these cells in the bone marrow , causing skeletal abnormalities. Abnormal blood cell production also occurs outside the bone marrow, affecting organs like the liver, spleen, and lymph nodes . This can lead to masses forming in the thorax, abdomen, and pelvis. Furthermore, the active blood cell production competes for nutrients with other deprived tissues, causing severe cachexia in untreated patients. Pathogenesis of B-thalassemia major. Note that the aggregates of unpaired a-globin chains, a hallmark of the disease, are not visible in routinely stained blood smears. Blood transfusions are a double-edged sword, diminishing the anemia and its attendant complications, but also adding to the systemic iron overload. HbA, Hemoglobin Peripheral smear: Blood smears show severe red cell abnormalities, including marked variation in size (anisocytosis) and shape (poikilocytosis) , microcytosis, and hypochromia . Target cells (so-called because hemoglobin collects in the center of the cell), basophilic stippling , and fragmented red cells also are common.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B,C & D are False.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 22-year-old female has congenital anemia that required multiple transfusions of PRBCs for many years. She now has no significant findings on physical examination. However, her liver function test results are abnormal. Which of the following findings would most likely appear in a liver biopsy:", "options": [{"label": "A", "text": "Steatosis in hepatocytes", "correct": false}, {"label": "B", "text": "Bilirubin in canaliculi", "correct": false}, {"label": "C", "text": "Glycogen in hepatocytes", "correct": false}, {"label": "D", "text": "Hemosiderin in hepatocytes", "correct": true}], "correct_answer": "D. Hemosiderin in hepatocytes", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemosiderin in hepatocytes In a 22-year-old female with congenital anemia who has received multiple transfusions of packed red blood cells (PRBCs) for many years and presents with abnormal liver function test results, the most likely finding in a liver biopsy would be D. Hemosiderin in hepatocytes . Hemosiderin is an insoluble form of iron that accumulates in tissues as a result of chronic red blood cell transfusions . In patients with chronic anemia requiring frequent transfusions , iron overloa d can occur, leading to the deposition of hemosiderin in various organs, including the liver. Hemosiderin is typically observed as golden-brown granules within hepatocytes in a liver biopsy .</p>\n<p><strong>Highyeild:</strong></p><p>Thalassemia major patients being dependent on regular blood transfusion are prone to iron overload which can affect various endocrine organs, heart, liver, over a period of time. Elevated ferritin concentration is considered a marker for high body iron stores . Prussian blue staining of the liver in Hereditary Hemochromatosis This iron overload can also damage the pancreas leading to the development of diabetes which is diagnosed by biochemical parameters. This type of diabetes is called “ Bronze Diabetes ” due to the greyish color of skin developed from the deposition of excess iron . Hereditary Hemochromatosis Mutations of genes encoding HFE, transferrin receptor 2 (TfR2), or hepcidin Mutations of genes encoding HJV (hemojuvelin: juvenile hemochromatosis) II. Hemosiderosis (Secondary Hemochromatosis) Parenteral iron overload due to red cell transfusions Severe chronic hemolytic anemias (e.g., sickle cell disease) Severe forms of thalassemia Bone marrow failure (e.g., aplastic anemia) Conditions associated with increased iron uptake β-Thalassemia Myelodysplastic syndrome Increased oral intake of iron African iron overload (Bantu siderosis) Congenital atransferrinemia Chronic liver disease Alcoholic liver disease Porphyria cutanea tarda Neonatal hemochromatosisa “Neonatal hemochromatosis develops in utero but does not appear to be a hereditary condition</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Steatosis in hepatocytes, is not the most likely finding in this scenario as it typically refers to the accumulation of fat in hepatocytes and is not directly related to chronic transfusions. Option: B. Bilirubin in canaliculi, is not the most likely finding in this case either. Bilirubin in canaliculi is associated with conditions such as cholestasis or impaired bile flow , which may present with jaundice and abnormal liver function tests, but it is not directly related to the chronic transfusion history mentioned. Option: C. Glycogen in hepatocytes, is not the most likely finding either. Glycogen accumulation in hepatocytes is associated with metabolic disorders such as glycogen storage diseases and is not directly related to the chronic transfusion history mentioned.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Iron metabolism and regulation are important for RBC precursor cells. Which of the following helps in the regulation of iron metabolism but is not specific for iron ?", "options": [{"label": "A", "text": "Hepcidin", "correct": false}, {"label": "B", "text": "DMT-1", "correct": true}, {"label": "C", "text": "Ferroportin", "correct": false}, {"label": "D", "text": "Ferritin", "correct": false}], "correct_answer": "B. DMT-1", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>DMT-1 Mucosal uptake of non-heme iron begins at the brush border of mucosal cells , mediated by divalent metal ion transporter 1 (DMT1) . Levels of DMT1 are markedly increased in iron-deficient animals . In addition to iron, DMT1 has been shown to transport a variety of divalent metal ions , including Mn 2+ , Co 2+ , Cu 2+ , Zn 2+ , Cd 2+ , and Pb 2+ . ( Hence non-specific ) It acts as a proton symporter ; protons accompany metal ions into the cell.</p>\n<p><strong>Highyeild:</strong></p><p>Iron transport: Regulation of iron absorption. Duodenal epithelial cell uptake of heme and nonheme iron is described in the text. When the storage sites of the body are replete with iron and erythropoietic activity is normal, plasma hepcidin balances iron uptake and loss to and maintains iron homeostasis by downregulating ferroportin and limiting iron uptake (middle panel). Hepcidin rises in the setting of systemic inflammation or when liver iron levels are high, decreasing iron uptake and increasing iron loss during the shedding of duodenocytes (right panel). Conversely, hepcidin levels fall in the setting of low plasma iron, primary hemochromatosis, or ineffective hematopoiesis (left panel), leading to a rise in iron absorption. DMTI, Divalent metal transporter I. Hepcidin: Iron absorption in the duodenum is regulated by hepcidin, a small circulating peptide that is synthesized and released from the liver in response to increases in intrahepatic iron levels. Hepcidin inhibits iron transfer from the enterocyte to plasma by binding to ferroportin , causing ferroportin to be endocytosed and degraded . As a result, as hepcidin levels rise , iron becomes trapped within duodenal cells in the form of mucosal ferritin and is lost as these cells slough . Ferroportin: It is a transmembrane protein that transports iron from the inside of a cell to the outside of the cell . Ferroportin is the only known iron exporter . Ferritin: The ferritin blood test measures how much iron is stored in a person’s body. Elevated ferritin concentration is considered a marker for high body iron stores .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hepcidin. Explained above. Option: C. Ferroportin. Explained above. Option: D. Ferritin. Explained above.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following correctly describes the principle of Prussian blue stain?", "options": [{"label": "A", "text": "Ferrocyanide to ferricyanide", "correct": false}, {"label": "B", "text": "Ferrocyanide to ferroferric cyanide", "correct": false}, {"label": "C", "text": "Ferroferric cyanide to ferrocyanide", "correct": false}, {"label": "D", "text": "Ferrocyanide to ferricferro cyanide", "correct": true}], "correct_answer": "D. Ferrocyanide to ferricferro cyanide", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Ferrocyanide to ferricferro cyanide Prussian Blue Stain: Purpose: To demonstrate ferric iron in tissue sections. Principle: The reaction occurs with the treatment of sections in acid solutions of ferrocyanides. Any ferric ion (+3) in the tissue combines with the ferrocyanide and results in the formation of a bright blue pigment called ‘Prussian blue” or ferric ferrocyanide . Hemosiderin is an insoluble form of iron that accumulates in tissues as a result of chronic red blood cell transfusions . In patients with chronic anemia requiring frequent transfusions , iron overloa d can occur, leading to the deposition of hemosiderin in various organs, including the liver. Hemosiderin is typically observed as golden-brown granules within hepatocytes in a liver biopsy .</p>\n<p><strong>Highyeild:</strong></p><p>Thalassemia major patients being dependent on regular blood transfusion are prone to iron overload which can affect various endocrine organs, heart, liver, over a period of time. Elevated ferritin concentration is considered a marker for high body iron stores . Prussian blue staining of the liver in Hereditary Hemochromatosis This iron overload can also damage the pancreas leading to the development of diabetes which is diagnosed by biochemical parameters. This type of diabetes is called “ Bronze Diabetes ” due to the greyish color of skin developed from the deposition of excess iron . Hereditary Hemochromatosis Mutations of genes encoding HFE, transferrin receptor 2 (TfR2), or hepcidin Mutations of genes encoding HJV (hemojuvelin: juvenile hemochromatosis) Hemosiderosis (Secondary Hemochromatosis) Parenteral iron overload due to red cell transfusions Severe chronic hemolytic anemias (e.g., sickle cell disease) Severe forms of thalassemia Bone marrow failure (e.g., aplastic anemia) Conditions associated with increased iron uptake β-Thalassemia Myelodysplastic syndrome Increased oral intake of iron African iron overload (Bantu siderosis) Congenital atransferrinemia Chronic liver disease Alcoholic liver disease Porphyria cutanea tarda Neonatal hemochromatosisa “Neonatal hemochromatosis develops in utero but does not appear to be a hereditary condition.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Ferrocyanide to ferricyanide. Incorrect . Option: B. Ferrocyanide to ferroferric cyanide. Incorrect . Option: C. Ferroferric cyanide to ferrocyanide. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Calculate the iron deficit for a 50 kg person, with Hb- 5g/dL. Add 1000 mg for stores.", "options": [{"label": "A", "text": "2150 mg", "correct": true}, {"label": "B", "text": "1650 mg", "correct": false}, {"label": "C", "text": "1150 mg", "correct": false}, {"label": "D", "text": "1575 mg", "correct": false}], "correct_answer": "A. 2150 mg", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>2150 mg Treatment of iron deficiency: The total dose is calculated from the amount of iron needed to restore the hemoglobin deficit plus an additional amount to replenish the stores. Iron requirement (mg) = 4.4 body weight (kg) × Hb deficit (g/dl) This formula includes the iron needed for replenishment of stores . Using this formula we get: 4 x 50 x (Target Hb (15) - Actual Hb) = 2200 mg Nearest correct Option: is A: 2150 mg . In other formula using hooch we get the same answer: Body weight (kg) × 2.3 × (15- patient's hemoglobin, g/dL) X + 500 or 1000 mg (for stores).</p>\n<p><strong>Highyeild:</strong></p><p>The rate of response with parenteral iron is not faster than with optimal doses given orally , except probably in the first 2–3 weeks when the dose of oral iron is being built up. However, iron stores can be replenished in a shorter time by parenteral therapy, because after correction of anemia, a smaller fraction of ingested iron is absorbed. Iron therapy by injection is indicated only when: Oral iron is not tolerated : bowel upset is too much. Failure to absorb oral iron : malabsorption; inflammatory bowel disease. Chronic inflammation (e.g. rheumatoid arthritis) decreases iron absorption, as well as the rate at which iron can be utilized. Non-compliance to oral iron . In the presence of severe deficiency with chronic bleeding . Along with erythropoietin in chronic kidney disease (CKD) patients : oral iron may not be absorbed at a sufficient rate to meet the demands of induced rapid erythropoiesis.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. 1650 mg. Incorrect . Option: C. 1150 mg. Incorrect . Option: D. 1575 mg. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Find the false statement regarding megaloblastic anemia", "options": [{"label": "A", "text": "Hypersegmented neutrophils are the earliest manifestation", "correct": false}, {"label": "B", "text": "Reticulocyte count decreased", "correct": false}, {"label": "C", "text": "Hypercellular bone marrow", "correct": false}, {"label": "D", "text": "MCHC is increased", "correct": true}], "correct_answer": "D. MCHC is increased", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>MCHC is increased Macrocytosis is a term used to describe erythrocytes that are larger than normal , typically reported as mean cell volume (MCV) greater than 100 fL . The amount of hemoglobin increases proportionately with the increase in cell size . Red cell indices in different anemias: table,tr,th,td {border:1px solid black;} Types of anemia MCV MCH MCHC Normocytic Normochromic Normal Normal Normal Microcytic Hypochromic Decreased Decreased Decreased Macrocytic Normochromic Increased Increased Normal</p>\n<p><strong>Highyeild:</strong></p><p>Megaloblastic anemia: The common theme among the various causes of megaloblastic anemia is an impairment of DNA synthesis that leads to ineffective hematopoiesis and distinctive morphologic changes , including abnormally large erythroid precursors and red cells . Vitamin B12 and Folic acid are coenzymes required for the synthesis of thymidine , one of the four bases found in DNA. A deficiency of these vitamins or impairment of their metabolism results in defective nuclear maturation due to deranged or inadequate DNA synthesis, with an attendant delay or block in cell division. Peripheral blood findings are common to all forms of megaloblastic anemia: Red cells that are macrocytic and oval (macro-ovalocytes) are highly characteristic. Marked variation in red cell size ( anisocytosis ) and shape ( poikilocytosis ). Neutrophils are also larger than normal and show nuclear hypersegmentation , having five or more nuclear lobules instead of the normal three to four. Megaloblastic anemia. A peripheral blood smear shows a hypersegmented neutrophil with a six-lobed nucleus Bone marrow is usually markedly hypercellular as a result of increased numbers of hematopoietic precursors. Megaloblastic changes are detected at all stages of erythroid development. The marrow hyperplasia is a response to increased levels of growth factors, such as erythropoietin . Although nuclear maturation is delayed, cytoplasmic maturation and hemoglobin accumulation proceed at a normal pace, leading to nuclear-to-cytoplasmic asynchrony . Because DNA synthesis is impaired in all proliferating cells, granulocytic precursors also display dysmaturation in the form of giant metamyelocytes and band forms .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hypersegmented neutrophils are the earliest manifestation. Correct . Option: B. Reticulocyte count decreased. Correct . Option: C. Hypercellular bone marrow. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Megaloblastic anemia that results from folic acid deficiency is identical to that encountered in vitamin B 12 deficiency. Thus, the diagnosis of Folate deficiency can be made only by demonstration of decreased serum or red cell folate levels . As in Vitamin B12 deficiency, serum homocysteine levels are increased , but methylmalonate concentrations are normal . Importantly, neurologic changes do not occur . Folate does not prevent (and may even exacerbate) the neurologic deficits seen in vitamin B12 deficiency states . It is thus essential to exclude vitamin B12 deficiency as the cause of megaloblastic anemia before initiating therapy with Folate .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "20-year-old female present with features of anemia. Blood tests: Hb-5g/dL, MCV – 52 fL, MCHC–20 g/dL, MCH – 22. Diagnosis:", "options": [{"label": "A", "text": "Folate deficiency", "correct": false}, {"label": "B", "text": "Diphyllobothrium lattum infection", "correct": false}, {"label": "C", "text": "Hookworm infection", "correct": true}, {"label": "D", "text": "Aplastic anemia", "correct": false}], "correct_answer": "C. Hookworm infection", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hookworm infection The findings in the question are suggestive of Microcytic anemia most likely Iron deficiency anemia . Hookworm infection can cause this among the given Option: MCV =PCV/RBC count (in millions) MCH= Hb/RBC count MCHC= Hb/ MCV In the above question, all three are low , pointing to Microcytic Hypochromic anemia , an example of that is iron deficiency anemia.</p>\n<p><strong>Highyeild:</strong></p><p>Adult Reference Ranges for Red Cells* Measurement (Units) Men Women Hemoglobin (g/dL) 13.6-17.2 12.0-15.0 Hematocrit (%) 39-49 33-43 Red cell count (×10/µL) 4.3-5.9 3.5-5.0 Reticulocyte count (%) 0.5-1.5 Mean cell volume (fL) 82-96 Mean cell hemoglobin (pg) 27-33 Mean cell hemoglobin concentration (g/dL) 33-37 Red cell distribution width 11.5-14.5 *Reference ranges vary among laboratories. The reference ranges for the laboratory providing the result should always be used in interpreting test results. Red cell indices in different anemias: Types of anemia MCV MCH MCHC Normocytic Normochromic Normal Normal Normal Microcytic Hypochromic Decreased Decreased Decreased Macrocytic Normochromic Increased Increased Normal Hookworm infection ( Necator americanus and Ancylostoma duodenale ) cause Iron deficiency anemia . They cause interruption of nutrient acquisition by the host through its ingestion and digestion of host blood . Trichuris trichura also causes Iron deficiency anemia along with Rectal prolapse .\\ Diphyllobothrium lattum causes Vitamin B12 deficiency .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Folate deficiency. Presents with Macrocytic Normochromic anemia . Option: B. Diphyllobothrium lattum infection. Presents with Vitamin B12 deficiency results in Macrocytic Normochromic anemia . Option: D. Aplastic anemia. Presents with Normocytic Normochromic anemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Most sensitive indicator of iron deficiency anemia:", "options": [{"label": "A", "text": "Packed cell volume", "correct": false}, {"label": "B", "text": "Hemoglobin", "correct": false}, {"label": "C", "text": "Serum ferritin", "correct": true}, {"label": "D", "text": "Serum iron", "correct": false}], "correct_answer": "C. Serum ferritin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Serum ferritin Among the Option:s provided, the most sensitive marker in iron deficiency anemia is Serum ferritin .</p>\n<p><strong>Highyeild:</strong></p><p>Serum ferritin reflects the storage of iron which is decreased even in the pre-latent stage of Iron deficiency Anemia and is the most sensitive marker . Free iron is highly toxic, and storage iron must therefore be sequestered. There are two forms of storage iron : a soluble form, known as ferritin and insoluble hemosiderin . Ferritin is found in all cells and in the highest concentration in the liver, spleen, and bone marrow . Investigation of a microcytic hypochromic anaemia. HbEP, haemoglobin electrophoresis; HPLC, high performance liquid chromatography.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Packed cell volume. Decreased, but not the most sensitive marker of iron deficiency anemia . Option: B. Hemoglobin. Decreased, but not the most sensitive marker of iron deficiency anemia . Option: D. Serum iron. Decreased, but not the most sensitive marker of iron deficiency anemia .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Most important inflammatory mediator, involved in anemia of chronic disease:", "options": [{"label": "A", "text": "IL-1", "correct": false}, {"label": "B", "text": "IL-6", "correct": true}, {"label": "C", "text": "TNF", "correct": false}, {"label": "D", "text": "IFN-γ", "correct": false}], "correct_answer": "B. IL-6", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>IL-6 Cytokines most often implicated in the pathogenesis of Anemia of Chronic Di sease (ACD) are TNF , IL-1 , IL-6 , and the interferons. However, IL-6 is the potent inducer of hepcidin , proposed as a major mediator of the iron abnormalities of ACD .</p>\n<p><strong>Highyeild:</strong></p><p>Anemia of Chronic Inflammation Impaired red cell production associated with chronic diseases that produce systemic inflammation is a common cause of anemia in hospitalized patients. This form of anemia stems from a reduction in the proliferation of erythroid progenitors and impaired iron utilization . The anemia of chronic inflammation is associated with Low serum iron Reduced total iron-binding capacity Abundant stored iron in tissue macrophages. Cytokines most often implicated in the pathogenesis of Anemia of Chronic Disease (ACD) are TNF , IL-1 , IL-6 , and interferons. However, IL-6 is the potent inducer of hepcidin , proposed as a major mediator of the iron abnormalities of ACD . Hepcidin inhibits ferroportin function in macrophages and reduces the transfer of iron from the storage pool to developing erythroid precursors in the bone marrow . As a result, the erythroid precursors are starved for iron in the midst of plenty.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. IL-1. Incorrect . Option: C. TNF. Incorrect . Option: D. IFN-γ. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "This patient came with anemia. This peripheral smear shows:", "options": [{"label": "A", "text": "Microcytic hypochromic anemia due to iron deficiency", "correct": false}, {"label": "B", "text": "Macrocytic anemia", "correct": true}, {"label": "C", "text": "Target cells of thalassemia", "correct": false}, {"label": "D", "text": "Spherocytes in autoimmune hemolytic anemia", "correct": false}], "correct_answer": "B. Macrocytic anemia", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686829342628-QTDP073079IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Macrocytic anemia The peripheral smear here shows hypersegmented neutrophils and macro-ovalocytes , suggestive of macrocytic anemia .</p>\n<p><strong>Highyeild:</strong></p><p>Megaloblastic anemia: The common theme among the various causes of megaloblastic anemia is an impairment of DNA synthesis that leads to ineffective hematopoiesis and distinctive morphologic changes , including abnormally large erythroid precursors and red cells . Vitamin B12 and Folic acid are coenzymes required for the synthesis of thymidine , one of the four bases found in DNA. A deficiency of these vitamins or impairment of their metabolism results in defective nuclear maturation due to deranged or inadequate DNA synthesis, with an attendant delay or block in cell division. Peripheral blood findings are common to all forms of megaloblastic anemia: Red cells that are macrocytic and oval (macro-ovalocytes) are highly characteristic. Marked variation in red cell size ( anisocytosis ) and shape ( poikilocytosis ). Neutrophils are also larger than normal and show nuclear hypersegmentation , having five or more nuclear lobules instead of the normal three to four. Megaloblastic anemia. A peripheral blood smear shows a hypersegmented neutrophil with a six-lobed nucleus. Bone marrow is usually markedly hypercellular as a result of increased numbers of hematopoietic precursors. Megaloblastic changes are detected at all stages of erythroid development. The marrow hyperplasia is a response to increased levels of growth factors, such as erythropoietin . Although nuclear maturation is delayed, cytoplasmic maturation and hemoglobin accumulation proceed at a normal pace, leading to nuclear-to-cytoplasmic asynchrony . Because DNA synthesis is impaired in all proliferating cells, granulocytic precursors also display dysmaturation in the form of giant metamyelocytes and band forms .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Microcytic hypochromic anemia due to iron deficiency. False . Option: C. Target cells of thalassemia. False . Option: D. Spherocytes in autoimmune hemolytic anemia. False .</p>\n<p><strong>Extraedge:</strong></p><p>Megaloblastic anemia that results from folic acid deficiency is identical to that encountered in vitamin B 12 deficiency. Thus, the diagnosis of Folate deficiency can be made only by demonstration of decreased serum or red cell folate levels . As in Vitamin B12 deficiency, serum homocysteine levels are increased , but methylmalonate concentrations are normal . Importantly, neurologic changes do not occur . Folate does not prevent (and may even exacerbate) the neurologic deficits seen in vitamin B12 deficiency states . It is thus essential to exclude vitamin B12 deficiency as the cause of megaloblastic anemia before initiating therapy with Folate .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Response to iron in iron deficiency anemia is denoted by:", "options": [{"label": "A", "text": "Restoration of enzymes", "correct": false}, {"label": "B", "text": "Reticulocytosis", "correct": true}, {"label": "C", "text": "Increase in iron binding capacity", "correct": false}, {"label": "D", "text": "Increase in hemoglobin", "correct": false}], "correct_answer": "B. Reticulocytosis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Reticulocytosis Response to iron therapy: Rapid subjective improvement , with a disappearance or marked diminution of fatigue, lassitude, and other nonspecific symptoms , before any improvement in anemia is observed. Earliest hematologic evidence of response to treatment is an increase in Reticulocytes % & Hb content . Maximal reticulocyte % is on the 5th to 10th day after the institution of therapy & thereafter returns to normal. Maximum value usually ranges from 5 to 10% and is inversely related to the level of hemoglobin. Hemoglobin level is the most accurate measure of the degree of anemia in iron deficiency .</p>\n<p><strong>Highyeild:</strong></p><p>Iron transport: Regulation of iron absorption. Duodenal epithelial cell uptake of heme and nonheme iron is described in the text. When the storage sites of the body are replete with iron and erythropoietic activity is normal, plasma hepcidin balances iron uptake and loss to and maintains iron homeostasis by downregulating ferroportin and limiting iron uptake (middle panel). Hepcidin rises in the setting of systemic inflammation or when liver iron levels are high, decreasing iron uptake and increasing iron loss during the shedding of duodenocytes (right panel). Conversely, hepcidin levels fall in the setting of low plasma iron, primary hemochromatosis, or ineffective hematopoiesis (left panel), leading to a rise in iron absorption. DMTI, Divalent metal transporter I. Hepcidin: Iron absorption in the duodenum is regulated by hepcidin, a small circulating peptide that is synthesized and released from the liver in response to increases in intrahepatic iron levels. Hepcidin inhibits iron transfer from the enterocyte to plasma by binding to ferroportin , causing ferroportin to be endocytosed and degraded . As a result, as hepcidin levels rise , iron becomes trapped within duodenal cells in the form of mucosal ferritin and is lost as these cells slough . Ferroportin: It is a transmembrane protein that transports iron from the inside of a cell to the outside of the cell . Ferroportin is the only known iron exporter . Ferritin: The ferritin blood test measures how much iron is stored in a person’s body. Elevated ferritin concentration is considered a marker for high body iron stores .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Restoration of enzymes. False . Option: C. Increase in iron binding capacity. False . Option: D. Increase in hemoglobin. False .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Iron deficiency causes", "options": [{"label": "A", "text": "Megaloblastic anemia", "correct": false}, {"label": "B", "text": "Microcytic hypochromic anemia, Mentzer index < 13", "correct": false}, {"label": "C", "text": "Macrocytic hypochromic anemia", "correct": false}, {"label": "D", "text": "Microcytic hypochromic anemia, Mentzer index > 13", "correct": true}], "correct_answer": "D. Microcytic hypochromic anemia, Mentzer index > 13", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Microcytic hypochromic anemia, Mentzer index > 13 Iron deficiency causes Microcytic hypochromic anemia . Iron deficiency (peripheral blood smear). Note the hypochromic microcytic red cells containing a narrow rim of peripheral hemoglobin. Scattered fully hemoglobinized cells, present due to recent blood transfusion, stand in contrast</p>\n<p><strong>Highyeild:</strong></p><p>Differential diagnosis of microcytic hypochromic RBCs: Iron Deficiency Anemia Anemia of Inflammation/chronic disease Thalassemia Sideroblastic Anemia Mentzer index: Used to differentiate Microcytic Hypochromic anemia caused by Iron deficiency anemia and beta thalassemia trait . Mentzer Index: MCV/RBC count If the quotient of the mean corpuscular volume (MCV, in fL) divided by the red blood cell count (RBC, in Millions per microLiter) is less than 13 , thalassemia trait is said to be more likely. If the result is greater than 13 , then iron-deficiency anemia is said to be more likely. The principle involved is as follows: In iron deficiency , the marrow cannot produce as many RBCs and they are small (microcytic), so the RBC count and the MCV will both be low and as a result, the index will be greater than 13 . Conversely, in thalassemia , which is a disorder of globin synthesis, the number of RBCs produced is normal, but the cells are smaller and more fragile. Therefore, the RBC count is normal, but the MCV is low , so the index will be less than 13 . REMEMBER: In Tha LESS emia, the Mentzer index is LESS than 13. table,tr,th,td {border:1px solid black;} In Iron deficiency In Thalassemia Bone marrow cannot produce as many RBCs and they are small (microcytic), so the RBC count as well as MCV is low Disorder of globin synthesis, RBC production is preserved, but the cells are smaller and more fragile. Therefore, the RBC count is normal with a low MCV Mentzer's index is>13 Q Mentzer's index is <13 Q</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Megaloblastic anemia. Seen with Vitamin B12 and Folate deficiency . Option: B. Microcytic hypochromic anemia Mentzer index < 13. Seen with Thalassemia . Option: C. Macrocytic hypochromic anemia. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "What is the most probable underlying diagnosis in a 30 years old female with an RBC count of 4.5 million, MCV 55 fL, Platelets 80,000/uL, with no history of blood transfusion?", "options": [{"label": "A", "text": "Iron deficiency anemia", "correct": false}, {"label": "B", "text": "Thalassemia major", "correct": false}, {"label": "C", "text": "Thalassemia minor", "correct": true}, {"label": "D", "text": "Megaloblastic anemia", "correct": false}], "correct_answer": "C. Thalassemia minor", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thalassemia minor Asymptomatic patient with microcytosis (MCV 55fL) and RBC count which is normal (4.5 million) is most likely to be Thalassemia trait .</p>\n<p><strong>Highyeild:</strong></p><p>Differential diagnosis of microcytic hypochromic RBCs: Iron Deficiency Anemia Anemia of Inflammation/chronic disease Thalassemia Sideroblastic Anemia Mentzer index: Used to differentiate Microcytic Hypochromic anemia caused by Iron deficiency anemia and beta thalassemia trait . Mentzer Index: MCV/RBC count If the quotient of the mean corpuscular volume (MCV, in fL) divided by the red blood cell count (RBC, in Millions per microLiter) is less than 13 , thalassemia trait is said to be more likely. If the result is greater than 13 , then iron-deficiency anemia is said to be more likely. The principle involved is as follows: In iron deficiency , the marrow cannot produce as many RBCs and they are small (microcytic), so the RBC count and the MCV will both be low and as a result, the index will be greater than 13 . Conversely, in thalassemia , which is a disorder of globin synthesis, the number of RBCs produced is normal, but the cells are smaller and more fragile. Therefore, the RBC count is normal, but the MCV is low , so the index will be less than 13 . REMEMBER: In Tha LESS emia, the Mentzer index is LESS than 13.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Iron deficiency anemia. Mentzer index greater than 13 . Option: B. Thalassemia major. Anemia manifests 6 to 9 months after birth as hemoglobin synthesis switches from HbF to HbA. Untreated children suffer from growth retardation and die at an early age from the effects of anemia. With transfusions and iron chelation, survival into the third decade is possible , but the overall outlook remains guarded. Option: D. Megaloblastic anemia. Macrocytic Normochromic anemia is seen.</p>\n<p><strong>Table:</strong></p><p>In Iron deficiency In Thalassemia Bone marrow cannot produce as many RBCs and they\n are small (microcytic), so the RBC count as well as MCV is low Disorder of globin synthesis, RBC production is\n preserved, but the cells are smaller and more fragile. Therefore, the RBC count is normal with a low MCV Mentzer's index is>13º Mentzer's index is <13º</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The pathogenesis of hypochromic anemia in lead poisoning is due to -", "options": [{"label": "A", "text": "Inhibition of enzymes involved in heme biosynthesis", "correct": true}, {"label": "B", "text": "Binding of lead to transferrin, inhibiting the transport of iron", "correct": false}, {"label": "C", "text": "Binding of lead to the cell membrane of erythroid precursors", "correct": false}, {"label": "D", "text": "Binding of lead to ferritin inhibiting their breakdown into hemosiderin", "correct": false}], "correct_answer": "A. Inhibition of enzymes involved in heme biosynthesis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Inhibition of enzymes involved in heme biosynthesis Lead has a high affinity for sulfhydryl groups and interferes with two enzymes involved in heme synthesis: delta-aminolevulinic acid dehydratase and ferrochelatase . Iron incorporation into heme is impaired, leading to microcytosis (small red cells) and anemia . Protoporphyrin is an intermediate in the pathway of heme synthesis. Lead inhibits heme synthesis by inhibiting ALA synthetase When heme synthesis is impaired, protoporphyrin accumulates within the red cell . This reflects an inadequate iron supply to erythroid precursors to support hemoglobin synthesis. Normal values are < 30 g/dL of red cells. In iron deficiency, values in excess of 100 g/dL are seen. The most common causes of increased red cell protoporphyrin levels are iron deficiency & lead poisoning . Blood and marrow changes occur fairly rapidly and are characteristic. The inhibition of ferrochelatase by lead may result in the appearance of a few ring sideroblasts , red cell precursors with iron-laden mitochondria that are detected with a Prussian blue stain. In the peripheral blood the defect in hemoglobin synthesis appears as a microcytic, hypochromic anemia that is often accompanied by mild hemolysis. Even more distinctive is a punctate basophilic stippling of the red cells .</p>\n<p><strong>Highyeild:</strong></p><p>Sideroblastic anemia occurs due to abnormal utilization of iron during erythropoiesis ie iron overloading type of presentation with Microcytic anemia & all lab findings are opposite to that of Iron Deficiency Anemia . Ring sideroblasts are seen in Bone Marrow . Treatment: Pyridoxine (Vit B6), as it is a cofactor for ALA synthase . Sideroblastic anemia is seen in: Lead poisoning Myelodysplastic syndrome Drugs ( isoniazid , pyrazinamide, chloramphenicol) Alcoholism Copper deficiency (zinc ingestion, copper chelation, nutritional, malabsorption) Hypothermia Ring sideroblasts with Prussian blue stain</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Binding of lead to transferrin, inhibiting the transport of iron. False . Option: C. Binding of lead to the cell membrane of erythroid precursors. False . Option: D. Binding of lead to ferritin inhibiting their breakdown into hemosiderin. False .</p>\n<p><strong>Table:</strong></p><p>Features\nof Lead poisoning: Children absorb more ingested lead than\n adults; the main source of exposure for children is lead-containing\n paint in older housing and lead-containing drinking water . Excess lead causes CNS defects in\n children and peripheral neuropathy in adults . It also\n interferes with the remodeling of cartilage and causes anemia by\n interfering with hemoglobin synthesis .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The following drug is not associated with pure red cell aplasia:", "options": [{"label": "A", "text": "Phenytoin", "correct": false}, {"label": "B", "text": "Isoniazid", "correct": false}, {"label": "C", "text": "Erythropoietin", "correct": true}, {"label": "D", "text": "None of the above", "correct": false}], "correct_answer": "C. Erythropoietin", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Erythropoietin Drugs associated with Pure Red Cell Aplasia (PRCA) are Phenytoin , Azathioprine , Chloramphenicol , Procainamide , and Isoniazid .</p>\n<p><strong>Highyeild:</strong></p><p>Pure red cell aplasia: Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed . In severe cases, red cell progenitors are completely absent from the marrow . It may occur in association with neoplasms , particularly thymoma and large granular lymphocytic leukemia , drug exposures , autoimmune disorders , and parvovirus infection . When a thymoma is present, resection leads to hematologic improvement in about one-half of the patients. In patients without thymoma , immunosuppressive therapy is often beneficial. Plasmapheresis also may be helpful in unusual patients with neutralizing antibodies to erythropoietin, which may appear de novo or following the administration of recombinant erythropoietin. A special form of red cell aplasia occurs in individuals infected with parvovirus B19 , which preferentially infects and destroys red cell progenitors. Normal individuals clear parvovirus infections within 1 to 2 weeks; as a result, the aplasia is transient and clinically unimportant.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Phenytoin. Causes pure red cell aplasia. Option: B. Isoniazid. Causes pure red cell aplasia.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pancytopenia with hypocellular bone marrow is seen in", "options": [{"label": "A", "text": "Fanconi’s anemia", "correct": true}, {"label": "B", "text": "Paroxysmal nocturnal hemoglobinuria", "correct": false}, {"label": "C", "text": "Hairy cell leukemia", "correct": false}, {"label": "D", "text": "Myelopthisis", "correct": false}], "correct_answer": "A. Fanconi’s anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fanconi’s anemia Fanconi anemia is a rare autosomal recessive disorder caused by defects in a multiprotein complex that is required for DNA repair. Marrow hypofunction becomes evident early in life and is often accompanied by multiple congenital anomalies , such as hypoplasia of the kidney and spleen, and bone anomalies, commonly involving the thumbs or radii.</p>\n<p><strong>Highyeild:</strong></p><p>Differential Diagnosis of Pancytopenia Pancytopenia with Hypocellular Bone Marrow Acquired aplastic anemia Constitutional aplastic anemia (Fanconi anemia, dyskeratosis congenita, and others) Hypocellular myelodysplastic syndrome Rare aleukemic leukemia Some acute lymphoid leukemia Rare lymphomas of bone marrow Copper deficiency Pancytopenia with Cellular Bone Marrow Primary bone marrow diseases Myelodysplastic syndromes Paroxysmal nocturnal hemoglobinuria (PNH) Myelofibrosis Aleukemic leukemia Myelophthisis Bone marrow lymphoma Hairy cell leukemia Secondary to systemic diseases Systemic lupus erythematosus Hypersplenism B 12, folate deficiency Copper deficiency Alcohol HIV infection Brucellosis Sarcoidosis Tuberculosis Leishmaniasis Sepsis Hypocellular Bone Marrow + Pancytopenia Q fever Legionnaires' disease Anorexia nervosa, starvation Mycobacterium</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:. B. Paroxysmal nocturnal hemoglobinuria. Shows Pancytopenia with Hypercellular Bone marrow . Option: C. Hairy cell leukemia. Shows Pancytopenia with Hypercellular Bone marrow . Option: D. Myelopthisis. Shows Pancytopenia with Hypercellular Bone marrow .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "2 y/o female presented with maculopapular rash 24hrs after the onset of mild fever. There was prominent erythema over the cheek. The causative organism also causes:", "options": [{"label": "A", "text": "CMV", "correct": false}, {"label": "B", "text": "ALL", "correct": false}, {"label": "C", "text": "DIC", "correct": false}, {"label": "D", "text": "PRCA", "correct": true}], "correct_answer": "D. PRCA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>PRCA In the case provided, the child develops maculopapular rash 24hrs after the onset of mild fever . There was prominent erythema over the cheek . It suggests Erythema infectiosum ( day 5 disease ) caused by parvovirus B19 infection . Parvovirus also causes an aplastic crisis in any hemolytic anemia due to suppression of early erythroblasts by acting on P receptors . Slapped cheek appearance is seen with Erythema infectiosum.</p>\n<p><strong>Highyeild:</strong></p><p>Pure red cell aplasia: Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed . In severe cases, red cell progenitors are completely absent from the marrow . It may occur in association with neoplasms , particularly thymoma and large granular lymphocytic leukemia , drug exposures , autoimmune disorders , and parvovirus infection . When a thymoma is present, resection leads to hematologic improvement in about one-half of the patients. In patients without thymoma , immunosuppressive therapy is often beneficial. Plasmapheresis also may be helpful in unusual patients with neutralizing antibodies to erythropoietin, which may appear de novo or following the administration of recombinant erythropoietin. A special form of red cell aplasia occurs in individuals infected with parvovirus B19 , which preferentially infects and destroys red cell progenitors. Normal individuals clear parvovirus infections within 1 to 2 weeks; as a result, the aplasia is transient and clinically unimportant.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. CMV. Incorrect . Option: B. ALL. Incorrect . Option: C. DIC. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Aplastic anemia can progress to all except:", "options": [{"label": "A", "text": "AML", "correct": false}, {"label": "B", "text": "Myelodysplastic anemia", "correct": false}, {"label": "C", "text": "Pure red cell aplasia", "correct": true}, {"label": "D", "text": "Paroxysmal nocturnal hemoglobinuria", "correct": false}], "correct_answer": "C. Pure red cell aplasia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pure red cell aplasia</p>\n<p><strong>Highyeild:</strong></p><p>Aplastic anemia can progress to AML Myelodysplastic anemia Paroxysmal nocturnal hemoglobinuria Aplastic anemia cannot progress to Pure red cell aplasia. As in In Aplastic anemia there is pancytopenia with bone marrow hypocellularity. Pancytopenia refers to: anemia, leukopenia, and thrombocytopenia . Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed . Aplastic anemia: The markedly hypocellular bone marrow is largely devoid of hematopoietic cells; often only fat cells, fibrous stroma, and scattered lymphocytes and plasma cells remain . Marrow aspirates often yield little material (a “dry tap”) ; hence, aplasia is best appreciated in marrow biopsies . Other nonspecific pathologic changes are related to granulocytopenia and thrombocytopenia, such as mucocutaneous bacterial infections and abnormal bleeding, respectively. Aplastic anemia (bone marrow biopsy). Markedlyhypocellular marrow contains mainly fat cells. (A) Low power. (B) High power. If the anemia necessitates multiple transfusions, systemic hemosiderosis can appear. Treatment: Steroids I/v Ig Anti Thymoside Globulin (ATG) Bone marrow Hematopoietic stem cell transplant</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. AML. Correct . Option: B. Myelodysplastic anemia. Correct . Option: D. Paroxysmal nocturnal hemoglobinuria. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Diagnostic criteria for severe aplastic anemia are all except", "options": [{"label": "A", "text": "Bone marrow cellularity of < 10%", "correct": true}, {"label": "B", "text": "Neutrophil count < 500/μl", "correct": false}, {"label": "C", "text": "Platelet count < 20,000/μl", "correct": false}, {"label": "D", "text": "Absolute reticulocyte count of < 60,000/μl", "correct": false}], "correct_answer": "A. Bone marrow cellularity of < 10%", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Bone marrow cellularity of < 10% Pancytopenia with hypocellular bone marrow < 25% cellularity along with other criteria are used for diagnosis of aplastic anemia.</p>\n<p><strong>Highyeild:</strong></p><p>Diagnostic criteria for aplastic anemia: Pancytopenia with hypocellular bone marrow < 25% cellularity along with 2 of the following: Absolute reticulocyte count < 60,000/µl Platelets < 20,000/µl Neutrophil count < 1500/µl Diagnostic criteria for severe aplastic anemia: Pancytopenia with hypocellular bone marrow < 25% cellularity along with 2 of the following: Absolute reticulocyte count < 60,000/µl Platelets < 20,000/µl Neutrophil count < 500/µl Diagnostic criteria for very severe aplastic anemia: Pancytopenia with hypocellular bone marrow < 25% cellularity along with 2 of the following: Absolute reticulocyte count < 60,000/µl Platelets < 20,000/µl Neutrophil count < 200/µl Aplastic anemia: The markedly hypocellular bone marrow is largely devoid of hematopoietic cells; often only fat cells, fibrous stroma, and scattered lymphocytes and plasma cells remain . Marrow aspirates often yield little material (a “dry tap”) ; hence, aplasia is best appreciated in marrow biopsies . Other nonspecific pathologic changes are related to granulocytopenia and thrombocytopenia, such as mucocutaneous bacterial infections and abnormal bleeding, respectively. Aplastic anemia (bone marrow biopsy). Markedlyhypocellular marrow contains mainly fat cells. (A) Low power. (B) High power. If the anemia necessitates multiple transfusions, systemic hemosiderosis can appear. Treatment: Steroids I/v Ig Anti Thymoside Globulin (ATG) Bone marrow Hematopoietic stem cell transplant</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Neutrophil count < 500/μl. Correct . Option: C. Platelet count < 20,000/μl. Correct . Option: D. Absolute reticulocyte count of < 60,000/μl. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The 2-year-old child presents with short stature and café-au-lait spots. Bone marrow aspiration yields little material and mostly contains fat. What is your diagnosis:", "options": [{"label": "A", "text": "Fanconi anemia", "correct": true}, {"label": "B", "text": "Dyskeratosis congenital", "correct": false}, {"label": "C", "text": "Tuberous sclerosis", "correct": false}, {"label": "D", "text": "Osteogenesis imperfecta", "correct": false}], "correct_answer": "A. Fanconi anemia", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Fanconi anemia The inherited bone marrow failure syndromes may primarily affect single or multiple hematopoietic lineages. Four inherited bone marrow failure syndromes associated with aplastic anemia : Fanconi anemia (FA) Dyskeratosis congenital (DC) Shwachman-Diamond syndrome (SDS) Congenital amegakaryocytic thrombocytopenia (CAMT) Fanconi anemia is a rare autosomal recessive disorder caused by defects in a multiprotein complex that is required for DNA repair. Marrow hypofunction becomes evident early in life and is often accompanied by multiple congenital anomalies , such as hypoplasia of the kidney and spleen, and bone anomalies, commonly involving the thumbs or radii. Physical Findings Associated with Fanconi Anemia Skeletal Short stature Radial ray anomalies (thumbs, hands, radii) Hip and spine anomalies Skin Hyperpigmentation (café au lait spots) Hypopigmentation Genitourinary Renal structural anomalies Hypogonadism Craniofacial Microcephaly Ophthalmic anomalies (microphthalmia, epicanthal folds) Otic anomalies (external and middle ear anomalies, deafness) Gastrointestinal malformations Esophageal atresia or tracheoesophageal fistula Imperforate anus Cardiac malformations</p>\n<p><strong>Highyeild:</strong></p><p>Differential Diagnosis of Pancytopenia Pancytopenia with Hypocellular Bone Marrow Acquired aplastic anemia Constitutional aplastic anemia (Fanconi anemia, dyskeratosis congenita, and others) Hypocellular myelodysplastic syndrome Rare aleukemic leukemia Some acute lymphoid leukemia Rare lymphomas of bone marrow Copper deficiency Pancytopenia with Cellular Bone Marrow Primary bone marrow diseases Myelodysplastic syndromes Paroxysmal nocturnal hemoglobinuria (PNH) Myelofibrosis Aleukemic leukemia Myelophthisis Bone marrow lymphoma Hairy cell leukemia Secondary to systemic diseases Systemic lupus erythematosus Hypersplenism B 12, folate deficiency Copper deficiency Alcohol HIV infection Brucellosis Sarcoidosis Tuberculosis Leishmaniasis Sepsis Hypocellular Bone Marrow + Pancytopenia Q fever Legionnaires' disease Anorexia nervosa, starvation Mycobacterium</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:. B. Dyskeratosis congenita. Characterized by the triad of mucous membrane leukoplakias, dystrophic nails, reticular hyperpigmentation , and with the development of aplastic anemia in childhood Option: C. Tuberous sclerosis. Is a rare genetic condition that causes mainly benign tumors to develop in different parts of the body . The tumors most often affect the brain, skin, kidneys, heart, eyes, and lungs. Tuberous sclerosis complex is caused by genetic mutations on either the TSC1 or TSC2 gene. Option: D. Osteogenesis imperfecta. Is a genetic disorder of connective tissues caused by an abnormality in the synthesis or processing of type I collagen . It is also called brittle bone disease . It is characterized by an increased susceptibility to bone fractures and decreased bone density, blue sclera,</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Most common tumor associated with pure red cell aplasia:", "options": [{"label": "A", "text": "Hepatoma", "correct": false}, {"label": "B", "text": "Hodgkins lymphoma", "correct": false}, {"label": "C", "text": "Thymoma", "correct": true}, {"label": "D", "text": "Bronchogenic carcinoma", "correct": false}], "correct_answer": "C. Thymoma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Thymoma Classification of Pure Red Cell Aplasia Self-limited Transient erythroblastopenia of childhood Transient aplastic crisis of hemolysis (acute B19 parvovirus infection) Fetal red blood cell aplasia Nonimmune hydrops fetalis (in utero B19 parvovirus infection) Hereditary pure red cel aplasia Congenital pure red cell aplasia (Diamond-Blackfan anemia) Acquired pure red cell aplasia Cancer Thymoma Lymphoid malignancies (and more rarely other hematologic diseases) Paraneoplastic to solid tumors Connective tissue disorders with immunologic abnormalities Systemic lupus erythematosus, juvenile rheumatoid arthritis, rheumatoid arthritis Multiple endocrine gland insufficiency Viruses Persistent B19 parvovirus, hepatitis, adult T cell leukemia virus, Epstein- Barr virus Pregnancy Drugs Especially phenytoin, azathioprine, chloramphenicol, procainamide, isoniazid Antibodies to erythropoietin Idiopathic</p>\n<p><strong>Highyeild:</strong></p><p>Pure red cell aplasia: Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed . In severe cases, red cell progenitors are completely absent from the marrow . It may occur in association with neoplasms , particularly thymoma and large granular lymphocytic leukemia , drug exposures , autoimmune disorders , and parvovirus infection . When a thymoma is present, resection leads to hematologic improvement in about one-half of the patients. In patients without thymoma , immunosuppressive therapy is often beneficial. Plasmapheresis also may be helpful in unusual patients with neutralizing antibodies to erythropoietin, which may appear de novo or following the administration of recombinant erythropoietin. A special form of red cell aplasia occurs in individuals infected with parvovirus B19 , which preferentially infects and destroys red cell progenitors. Normal individuals clear parvovirus infections within 1 to 2 weeks; as a result, the aplasia is transient and clinically unimportant.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Hepatoma. Incorrect . Option: B. Hodgkin’s lymphoma. Incorrect . Option: D. Bronchogenic carcinoma. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pure red cell aplasia is associated with all except:", "options": [{"label": "A", "text": "ABO incompatibility after renal transplant", "correct": false}, {"label": "B", "text": "5q- syndrome", "correct": true}, {"label": "C", "text": "Drugs", "correct": false}, {"label": "D", "text": "Large granular lymphocytic leukemia", "correct": false}], "correct_answer": "B. 5q- syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>5q- syndrome Pure red cell aplasia is not associated with 5q- syndrome Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed. Classification of Pure Red Cell Aplasia Self-limited Transient erythroblastopenia of childhood Transient aplastic crisis of hemolysis (acute B19 parvovirus infection) Fetal red blood cell aplasia Nonimmune hydrops fetalis (in utero B19 parvovirus infection) Hereditary pure red cel aplasia Congenital pure red cell aplasia (Diamond-Blackfan anemia) Acquired pure red cell aplasia Cancer Thymoma Lymphoid malignancies (and more rarely other hematologic diseases) Paraneoplastic to solid tumors Connective tissue disorders with immunologic abnormalities Systemic lupus erythematosus, juvenile rheumatoid arthritis, rheumatoid arthritis Multiple endocrine gland insufficiency Viruses Persistent B19 parvovirus, hepatitis, adult T cell leukemia virus, Epstein- Barr virus Pregnancy Drugs Especially phenytoin, azathioprine, chloramphenicol, procainamide, isoniazid Antibodies to erythropoietin Idiopathic</p>\n<p><strong>Highyeild:</strong></p><p>Pure red cell aplasia: Pure red cell aplasia is a primary marrow disorder in which only erythroid progenitors are suppressed . In severe cases, red cell progenitors are completely absent from the marrow . It may occur in association with neoplasms , particularly thymoma and large granular lymphocytic leukemia , drug exposures , autoimmune disorders , and parvovirus infection . When a thymoma is present, resection leads to hematologic improvement in about one-half of the patients. In patients without thymoma , immunosuppressive therapy is often beneficial. Plasmapheresis also may be helpful in unusual patients with neutralizing antibodies to erythropoietin, which may appear de novo or following the administration of recombinant erythropoietin. A special form of red cell aplasia occurs in individuals infected with parvovirus B19 , which preferentially infects and destroys red cell progenitors. Normal individuals clear parvovirus infections within 1 to 2 weeks; as a result, the aplasia is transient and clinically unimportant.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. ABO incompatibility after renal transplant. Correct . Option: C. Drugs. Correct . Option: D. Large granular lymphocytic leukemia. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Pancytopenia with cellular bone marrow is seen in all except", "options": [{"label": "A", "text": "Megaloblastic Anemia", "correct": false}, {"label": "B", "text": "MDS", "correct": false}, {"label": "C", "text": "PNH", "correct": false}, {"label": "D", "text": "G6PD deficiency", "correct": true}], "correct_answer": "D. G6PD deficiency", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>G6PD deficiency Pancytopenia with cellular bone marrow is not seen in G6PD deficiency, which is a type of hemolytic anemia .</p>\n<p><strong>Highyeild:</strong></p><p>Differential Diagnosis of Pancytopenia Pancytopenia with Hypocellular Bone Marrow Acquired aplastic anemia Constitutional aplastic anemia (Fanconi anemia, dyskeratosis congenita, and others) Hypocellular myelodysplastic syndrome Rare aleukemic leukemia Some acute lymphoid leukemia Rare lymphomas of bone marrow Copper deficiency Pancytopenia with Cellular Bone Marrow Primary bone marrow diseases Myelodysplastic syndromes Paroxysmal nocturnal hemoglobinuria (PNH) Myelofibrosis Aleukemic leukemia Myelophthisis Bone marrow lymphoma Hairy cell leukemia Secondary to systemic diseases Systemic lupus erythematosus Hypersplenism B 12, folate deficiency Copper deficiency Alcohol HIV infection Brucellosis Sarcoidosis Tuberculosis Leishmaniasis Sepsis Hypocellular Bone Marrow + Pancytopenia Q fever Legionnaires' disease Anorexia nervosa, starvation Mycobacterium</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option:. A. Megaloblastic Anemia. Shows Pancytopenia with Hypercellular Bone marrow . Option: B. MDS. Shows Pancytopenia with Hypercellular Bone marrow . Option: C. PNH. Shows Pancytopenia with Hypercellular Bone marrow .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 39 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "Cells seen in chronic infection of pseudomonas:-", "options": [{"label": "A", "text": "Neutrophils", "correct": true}, {"label": "B", "text": "Eosinophils", "correct": false}, {"label": "C", "text": "Lymphocytes", "correct": false}, {"label": "D", "text": "Macrophage", "correct": false}], "correct_answer": "A. Neutrophils", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Neutrophils Acute inflammation : mediator is Neutrophils (except in typhoid which are lymphocytes) . Chronic inflammation : mediators are lymphocytes , macrophages , and plasma cells (except in chronic pseudomonas which is neutrophils) .</p>\n<p><strong>Highyeild:</strong></p><p>Neutrophil extracellular traps (NETs) Neutrophil extracellular traps are extracellular fibrillar networks that concentrate antimicrobial substances at sites of infection and trap microbes, helping to prevent their spread. They are produced by neutrophils in response to infectious pathogens ( mainly bacteria and fungi ) and inflammatory mediators (e.g., chemokines, cytokines [mainly interferons], complement proteins, and ROS ). The extracellular traps consist of a viscous meshwork of nuclear chromatin that binds and concentrates granule proteins such as antimicrobial peptides and enzymes. In this process, the nuclei of the neutrophils are lost, leading to the death of the cells .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Eosinophils. Seen in helminthic infections and allergic reactions . Option: C. Lymphocytes. Seen in viral infections and chronic inflammation. Option: D. Macrophage. Seen in Chronic inflammation and some hypersensitivity reactions .</p>\n<p><strong>Extraedge:</strong></p><p>The nuclear chromatin in the NETs , which includes histones and associated DNA, has been postulated to be a source of nuclear antigens in systemic autoimmune diseases , particularly lupus , in which individuals react against their own DNA and nucleoproteins. Neutrophil extracellular traps (NETS). (A) Healthy neutrophils with nuclei stained red and cytoplasm stained green. (B) Release of nuclear material from neutrophils (note that two have lost their nuclei), forming extracellular traps. (C) Electron micrograph of bacteria (staphylococci) trapped in NETS. (From Brinkmann V, Zychlinsky A: Beneficial suicide: why neutrophils die to make NETS, Nat Rev Microbiol 5:577, 2007, with permission.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 11 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "All of the following statements are true regarding spider telangiectasias except:", "options": [{"label": "A", "text": "These are neoplastic lesions", "correct": true}, {"label": "B", "text": "These manifest as radial, often pulsatile arrays of dilated subcutaneous arteries or arterioles about a central core", "correct": false}, {"label": "C", "text": "These commonly occur on the face, neck, or upper chest", "correct": false}, {"label": "D", "text": "These are most frequently associated with hyperestrogenic states, such as pregnancy or liver cirrhosis", "correct": false}], "correct_answer": "A. These are neoplastic lesions", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>These are neoplastic lesions</p>\n<p><strong>Highyeild:</strong></p><p>Spider telangiectasias are non-neoplastic vascular lesions grossly resembling a spider. These manifest as radial , often pulsatile arrays of dilated subcutaneous arteries or arterioles (resembling spider legs) about a central core (resembling a spider’s body) that blanch with pressure . These commonly occur on the face, neck, or upper chest (along with the distribution of SVC) and are most frequently associated with hyperestrogenic states , such as pregnancy or liver cirrhosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. These manifest as radial, often pulsatile arrays of dilated subcutaneous arteries or arterioles about a central core. Correct . Option: C. These commonly occur on the face, neck, or upper chest. Correct . Option: D. These are most frequently associated with hyperestrogenic states, such as pregnancy or liver cirrhosis. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding hemangioma except:", "options": [{"label": "A", "text": "These are present from birth and initially increase in size, but many eventually regress", "correct": false}, {"label": "B", "text": "Hemangioma typically are localized lesions confined to the head and neck", "correct": false}, {"label": "C", "text": "Nearly one-third of these internal lesions are found in the lung", "correct": true}, {"label": "D", "text": "Malignant transformation is rare", "correct": false}], "correct_answer": "C. Nearly one-third of these internal lesions are found in the lung", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Nearly one-third of these internal lesions are found in the lung False , nearly one-third of internal lesions occur in the liver .</p>\n<p><strong>Highyeild:</strong></p><p>Hemangiomas Hemangiomas are very common tumors composed of blood-filled vessels . Most are present from birth and initially increase in size , but many eventually regress spontaneously. While hemangiomas are typically confined to the head, neck, and thoracic skin , they can also arise internally and can occasionally be more extensive ( angiomatosis ) Nearly one-third of internal lesions occur in the liver Malignant transformation is rare . Several histologic and clinical variants have been described. Capillary hemangiomas are the most common type; these occur in the skin , subcutaneous tissues , and mucous membranes of the oral cavities and lips, as well as in the liver, spleen, and kidneys . Histologically, they are composed of thin-walled capillaries with scant stroma . Juvenile hemangiomas (so-called strawberry-type hemangiomas ) of the newborn skin are extremely common (1 in 200 births) and can be multiple . These grow rapidly for a few months but then fade by 1 to 3 years of age and completely regress by age 7 in most cases. Cavernous hemangiomas are composed of large, dilated vascular channels . In contradistinction to capillary hemangiomas, cavernous hemangiomas are more infiltrative, frequently involve deep structures, and do not spontaneously regress . Moreover, cavernous hemangiomas detected by imaging studies may be difficult to distinguish from their malignant counterparts. On histologic examination, the mass is sharply delineated but unencapsulated and composed of large, cavernous blood-filled vascular spaces , separated by connective tissue stroma . Intravascular thrombosis with associated dystrophic calcification is common. They can be locally destructive , but more often are of little clinical significance outside of a cosmetic disfigurement or their vulnerability to traumatic ulceration and bleeding. Brain hemangiomas are problematic, as they can cause symptoms related to compression of adjacent tissue or rupture . Cavernous hemangiomas are one component of von Hippel-Lindau disease , in which vascular lesions are commonly found in the cerebellum, brain stem, retina, pancreas, and liver.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. These are present from birth and initially increase in size, but many eventually regress. Correct . Option: B. Hemangiomas typically are localized lesions confined to the head and neck. Correct . Option: D. Malignant transformation is rare. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Pyogenic granulomas are capillary hemangiomas that present as rapidly growing red pedunculated lesions on the skin, gingiva, or oral mucosa . They bleed easily and are often ulcerated. Roughly a quarter of lesions develop after trauma , reaching a size of 1 to 2 cm within a few weeks. Curettage and cautery are usually curative. A pregnancy tumor (granuloma gravidarum) is a pyogenic granuloma that occurs infrequently (in 1% of patients) in the gingiva of pregnant women . These lesions may spontaneously regress (especially after pregnancy) or undergo fibrosis but occasionally require surgical excision. Hemangiomas. (A) Hemangioma of the tongue. (B) Histology of juvenile capillary hemangioma. (C) Histology of cavernous hemangioma. (D) Pyogenic granuloma of the lip. (A and D, Courtesy John Sexton, MD, Beth Israel Hospital, Boston, Mass.; B, courtesy Christopher D. M. Fletcher, MD, Brigham and Women's Hospital, Boston, Mass.; and C, courtesy Thomas Rogers, MD, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The histopathological picture of blood-filled vascular channels separated by connective tissue stroma identifies the lesion:", "options": [{"label": "A", "text": "Arteriovenous malformation", "correct": false}, {"label": "B", "text": "Cavernous hemangioma", "correct": true}, {"label": "C", "text": "Pyogenic hemangioma", "correct": false}, {"label": "D", "text": "Spider telangiectasia", "correct": false}], "correct_answer": "B. Cavernous hemangioma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831210667-QTDP093005IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Cavernous hemangioma On histologic examination, the mass is unencapsulated , has infiltrative borders , and is composed of large, cavernous blood-filled vascular spaces separated by connective tissue stroma , suggestive of Cavernous Hemangioma .</p>\n<p><strong>Highyeild:</strong></p><p>Hemangiomas Hemangiomas are very common tumors composed of blood-filled vessels . Most are present from birth and initially increase in size , but many eventually regress spontaneously. While hemangiomas are typically confined to the head, neck, and thoracic skin , they can also arise internally and can occasionally be more extensive ( angiomatosis ). Nearly one-third of internal lesions occur in the liver . Malignant transformation is rare . Several histologic and clinical variants have been described. Capillary hemangiomas are the most common type; these occur in the skin , subcutaneous tissues , and mucous membranes of the oral cavities and lips, as well as in the liver, spleen, and kidneys . Histologically, they are composed of thin-walled capillaries with scant stroma . Juvenile hemangiomas (so-called strawberry-type hemangiomas ) of the newborn skin are extremely common (1 in 200 births) and can be multiple . These grow rapidly for a few months but then fade by 1 to 3 years of age and completely regress by age 7 in most cases. Cavernous hemangiomas are composed of large, dilated vascular channels . In contradistinction to capillary hemangiomas, cavernous hemangiomas are more infiltrative, frequently involve deep structures, and do not spontaneously regress . Moreover, cavernous hemangiomas detected by imaging studies may be difficult to distinguish from their malignant counterparts. On histologic examination, the mass is sharply delineated but unencapsulated and composed of large, cavernous blood-filled vascular spaces , separated by connective tissue stroma . Intravascular thrombosis with associated dystrophic calcification is common. They can be locally destructive , but more often are of little clinical significance outside of a cosmetic disfigurement or their vulnerability to traumatic ulceration and bleeding. Brain hemangiomas are problematic, as they can cause symptoms related to compression of adjacent tissue or rupture . Cavernous hemangiomas are one component of von Hippel-Lindau disease , in which vascular lesions are commonly found in the cerebellum, brain stem, retina, pancreas, and liver.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Arteriovenous malformation. Incorrect . Option: C. Pyogenic hemangioma. Incorrect . Option: D. Spider telangiectasia. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Pyogenic granulomas are capillary hemangiomas that present as rapidly growing red pedunculated lesions on the skin, gingiva, or oral mucosa . They bleed easily and are often ulcerated. Roughly a quarter of lesions develop after trauma , reaching a size of 1 to 2 cm within a few weeks. Curettage and cautery are usually curative. A pregnancy tumor (granuloma gravidarum) is a pyogenic granuloma that occurs infrequently (in 1% of patients) in the gingiva of pregnant women . These lesions may spontaneously regress (especially after pregnancy) or undergo fibrosis but occasionally require surgical excision. Hemangiomas. (A) Hemangioma of the tongue. (B) Histology of juvenile capillary hemangioma. (C) Histology of cavernous hemangioma. (D) Pyogenic granuloma of the lip. (A and D, Courtesy John Sexton, MD, Beth Israel Hospital, Boston, Mass.; B, courtesy Christopher D. M. Fletcher, MD, Brigham and Women's Hospital, Boston, Mass.; and C, courtesy Thomas Rogers, MD, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A pregnancy tumor is a type of-", "options": [{"label": "A", "text": "Arterio venous malformation", "correct": false}, {"label": "B", "text": "Cavernous hemangioma", "correct": false}, {"label": "C", "text": "Pyogenic hemangioma", "correct": true}, {"label": "D", "text": "Spider telangiectasia", "correct": false}], "correct_answer": "C. Pyogenic hemangioma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pyogenic hemangioma Pregnancy tumor (granuloma gravidarum) is a pyogenic granuloma that occurs infrequently (1% of patients) in the gingiva of pregnant women .</p>\n<p><strong>Highyeild:</strong></p><p>Hemangiomas Hemangiomas are very common tumors composed of blood-filled vessels . Most are present from birth and initially increase in size , but many eventually regress spontaneously. While hemangiomas are typically confined to the head, neck, and thoracic skin , they can also arise internally and can occasionally be more extensive ( angiomatosis ). Nearly one-third of internal lesions occur in the liver . Malignant transformation is rare . Several histologic and clinical variants have been described. Capillary hemangiomas are the most common type; these occur in the skin , subcutaneous tissues , and mucous membranes of the oral cavities and lips, as well as in the liver, spleen, and kidneys . Histologically, they are composed of thin-walled capillaries with scant stroma . Juvenile hemangiomas (so-called strawberry-type hemangiomas ) of the newborn skin are extremely common (1 in 200 births) and can be multiple . These grow rapidly for a few months but then fade by 1 to 3 years of age and completely regress by age 7 in most cases. Cavernous hemangiomas are composed of large, dilated vascular channels . In contradistinction to capillary hemangiomas, cavernous hemangiomas are more infiltrative, frequently involve deep structures, and do not spontaneously regress . Moreover, cavernous hemangiomas detected by imaging studies may be difficult to distinguish from their malignant counterparts. On histologic examination, the mass is sharply delineated but unencapsulated and composed of large, cavernous blood-filled vascular spaces , separated by connective tissue stroma . Intravascular thrombosis with associated dystrophic calcification is common. They can be locally destructive , but more often are of little clinical significance outside of a cosmetic disfigurement or their vulnerability to traumatic ulceration and bleeding. Brain hemangiomas are problematic, as they can cause symptoms related to compression of adjacent tissue or rupture . Cavernous hemangiomas are one component of von Hippel-Lindau disease , in which vascular lesions are commonly found in the cerebellum, brain stem, retina, pancreas, and liver.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Arteriovenous malformation. Incorrect . Option: B. Cavernous hemangioma. Incorrect . Option: D. Spider telangiectasia. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>Pyogenic granulomas are capillary hemangiomas that present as rapidly growing red pedunculated lesions on the skin, gingiva, or oral mucosa . They bleed easily and are often ulcerated. Roughly a quarter of lesions develop after trauma , reaching a size of 1 to 2 cm within a few weeks. Curettage and cautery are usually curative. A pregnancy tumor (granuloma gravidarum) is a pyogenic granuloma that occurs infrequently (in 1% of patients) in the gingiva of pregnant women . These lesions may spontaneously regress (especially after pregnancy) or undergo fibrosis but occasionally require surgical excision. Hemangiomas. (A) Hemangioma of the tongue. (B) Histology of juvenile capillary hemangioma. (C) Histology of cavernous hemangioma. (D) Pyogenic granuloma of the lip. (A and D, Courtesy John Sexton, MD, Beth Israel Hospital, Boston, Mass.; B, courtesy Christopher D. M. Fletcher, MD, Brigham and Women's Hospital, Boston, Mass.; and C, courtesy Thomas Rogers, MD, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A patient has repeated trauma over the gingival mucosa and presented to the clinician as a red pedunculated lesion that bleeds on the touch and is ulcerated, surgical excision was done, and histopathological picture shows. Identify the lesion:", "options": [{"label": "A", "text": "Pyogenic granuloma", "correct": true}, {"label": "B", "text": "Cavernous hemangioma", "correct": false}, {"label": "C", "text": "AV malformation", "correct": false}, {"label": "D", "text": "Vascular Ectasia", "correct": false}], "correct_answer": "A. Pyogenic granuloma", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831210980-QTDP093007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pyogenic granuloma</p>\n<p><strong>Highyeild:</strong></p><p>Hemangiomas Hemangiomas are very common tumors composed of blood-filled vessels . Most are present from birth and initially increase in size , but many eventually regress spontaneously. While hemangiomas are typically confined to the head, neck, and thoracic skin , they can also arise internally and can occasionally be more extensive ( angiomatosis ). Nearly one-third of internal lesions occur in the liver . Malignant transformation is rare . Several histologic and clinical variants have been described. Capillary hemangiomas are the most common type; these occur in the skin , subcutaneous tissues , and mucous membranes of the oral cavities and lips, as well as in the liver, spleen, and kidneys . Histologically, they are composed of thin-walled capillaries with scant stroma . Juvenile hemangiomas (so-called strawberry-type hemangiomas ) of the newborn skin are extremely common (1 in 200 births) and can be multiple . These grow rapidly for a few months but then fade by 1 to 3 years of age and completely regress by age 7 in most cases. Cavernous hemangiomas are composed of large, dilated vascular channels . In contradistinction to capillary hemangiomas, cavernous hemangiomas are more infiltrative, frequently involve deep structures, and do not spontaneously regress . Moreover, cavernous hemangiomas detected by imaging studies may be difficult to distinguish from their malignant counterparts. On histologic examination, the mass is sharply delineated but unencapsulated and composed of large, cavernous blood-filled vascular spaces , separated by connective tissue stroma . Intravascular thrombosis with associated dystrophic calcification is common. They can be locally destructive , but more often are of little clinical significance outside of a cosmetic disfigurement or their vulnerability to traumatic ulceration and bleeding. Brain hemangiomas are problematic, as they can cause symptoms related to compression of adjacent tissue or rupture . Cavernous hemangiomas are one component of von Hippel-Lindau disease , in which vascular lesions are commonly found in the cerebellum, brain stem, retina, pancreas, and liver. Pyogenic granulomas are capillary hemangiomas that present as rapidly growing red pedunculated lesions on the skin, gingiva, or oral mucosa . They bleed easily and are often ulcerated. Roughly a quarter of lesions develop after trauma , reaching a size of 1 to 2 cm within a few weeks. Curettage and cautery are usually curative. A pregnancy tumor (granuloma gravidarum) is a pyogenic granuloma that occurs infrequently (in 1% of patients) in the gingiva of pregnant women . These lesions may spontaneously regress (especially after pregnancy) or undergo fibrosis but occasionally require surgical excision. Hemangiomas. (A) Hemangioma of the tongue. (B) Histology of juvenile capillary hemangioma. (C) Histology of cavernous hemangioma. (D) Pyogenic granuloma of the lip. (A and D, Courtesy John Sexton, MD, Beth Israel Hospital, Boston, Mass.; B, courtesy Christopher D. M. Fletcher, MD, Brigham and Women's Hospital, Boston, Mass.; and C, courtesy Thomas Rogers, MD, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: B. Cavernous hemangioma. Incorrect . Option: C. AV malformation. Incorrect . Option: D. Vascular Ectasia. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding cavernous lymphangioma except:", "options": [{"label": "A", "text": "It is typically seen in the neck and axilla of children", "correct": false}, {"label": "B", "text": "It produces gross deformity", "correct": false}, {"label": "C", "text": "Histologically present as dilated lymphatic spaces lined by endothelial cells and separated by intervening connective tissue stroma containing lymphoid aggregates", "correct": false}, {"label": "D", "text": "Most commonly associated with Down syndrome", "correct": true}], "correct_answer": "D. Most commonly associated with Down syndrome", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Most commonly associated with Down syndrome</p>\n<p><strong>Highyeild:</strong></p><p>Cavernous lymphangiomas ( Cystic Hygromas ) are typically found in the neck or axilla of children , and more rarely in the retroperitoneum. Cavernous lymphangiomas can occasionally be enormous (up to 15 cm in diameter) and may fill the axilla or produce gross deformities about the neck, occasionally may present at birth and be so large as to obstruct labor . Of note, cavernous lymphangiomas of the neck are common in Turner syndrome . These lesions are composed of massively dilated lymphatic spaces lined by endothelial cells and separated by intervening connective tissue stroma containing lymphoid aggregates . The tumor margins are indistinct and unencapsulated , making definitive resection difficult . The swelling may be bilateral and is soft and partially compressible , visibly increasing in size when the child coughs or cries . The characteristic that distinguishes it from all other neck swellings is that it is brilliantly transilluminate . Definitive treatment involving complete excision of the cyst at an early stage is best if possible. Injection of a sclerosing agent is an alternative strategy and may reduce the size of the cyst; however, they are commonly multicystic, and therefore the complete resolution is a challenge .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. It is typically seen in the neck and axilla of children. Correct . Option: B. It produces gross deformity. Correct . Option: C. Histologically present as dilated lymphatic spaces lined by endothelial cells and separated by intervening connective tissue stroma containing lymphoid aggregates. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Which of the following is classified into the intermediate grade neoplasm in the classification of vascular tumors and tumor-like conditions:", "options": [{"label": "A", "text": "Angiosarcoma", "correct": false}, {"label": "B", "text": "Hemangiopericytoma", "correct": false}, {"label": "C", "text": "Bacillary angiomatosis", "correct": false}, {"label": "D", "text": "Hemangioendothelioma", "correct": true}], "correct_answer": "D. Hemangioendothelioma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Hemangioendothelioma Malignant neoplasm Angiosarcoma Hemangiopericytoma Intermediate grade neoplasm Kaposi sarcoma Hemangioendothelioma</p>\n<p><strong>Highyeild:</strong></p><p>Kaposi Sarcoma: Kaposi sarcoma ( KS ) is a vascular neoplasm caused by human herpesvirus 8 (HHV8, also known as Kaposi sarcoma herpesvirus). Although it occurs in a number of contexts, it is by far the most common in patients with AIDS ; indeed, its presence is used as a criterion for the diagnosis of AIDS . Based on population demographics and risk factors, KS is categorized into four forms : Classic KS is a disorder of older men . It can be associated with malignancy or altered immunity , but it is NOT associated with HIV Classic KS manifests as multiple red-purple skin plaques or nodules , usually in the distal lower extremities ; these progressively increase in size and number and spread proximally . Although persistent, the tumors are typically asymptomatic and remain localized to the skin and subcutaneous tissue. B typically occurs in HIV seronegative individuals younger than age 40 years and can follow an indolent or aggressive course; it involves lymph nodes much more frequently than the classic variant. Transplant-associated KS occurs in solid-organ transplant recipients receiving T-cell immunosuppression; the risk can be 100-fold greater than for immunocompetent patients. Transplant-associated KS typically follows an aggressive course involving lymph nodes , mucosa , and viscera ; cutaneous lesions may be absent. Lesions can regress as immunosuppression is reduced but at the risk of organ rejection. AIDS-associated (epidemic) KS is an AIDS-defining illness ; worldwide, it represents the Most Common HIV-related malignancy . Although the incidence of KS has fallen more than 80% with the advent of aggressive antiretroviral therapies, it still occurs in HIV-infected individuals 300-fold more commonly than in transplant recipients and 1000-fold greater than in the general population. AIDS-associated KS often involves lymph nodes and disseminates widely to viscera early in its course; most patients eventually die of opportunistic infections rather than KS . Cutaneous lesions may occur alone or with visceral lesions of the oral cavity, gastrointestinal tract, and respiratory system. The presence of extensive oral Kaposi sarcoma, as seen in this patient, is associated with a poor prognosis .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. Angiosarcomas are malignant endothelial neoplasms. Option: B. Hemangiopericytomas are rare tumors derived from pericytes surrounding the blood vessels and are mostly malignant . Option: C. Bacillary angiomatosis. Bacillary angiomatosis is a vascular proliferation in immunocompromised hosts (e.g., patients with AIDS by opportunistic bacilli of the Bartonella family . Lesions can involve the skin, bone, brain, and other organs. The infections (and lesions) are cleared by antibiotics .</p>\n<p><strong>Extraedge:</strong></p><p>Classic KS is a disorder of older men . It can be associated with malignancy or altered immunity , but it is NOT associated with HIV Classic KS manifests as multiple red-purple skin plaques or nodules , usually in the distal lower extremities ; these progressively increase in size and number and spread proximally . Although persistent, the tumors are typically asymptomatic and remain localized to the skin and subcutaneous tissue. B typically occurs in HIV seronegative individuals younger than age 40 years and can follow an indolent or aggressive course; it involves lymph nodes much more frequently than the classic variant. Transplant-associated KS occurs in solid-organ transplant recipients receiving T-cell immunosuppression; the risk can be 100-fold greater than for immunocompetent patients. Transplant-associated KS typically follows an aggressive course involving lymph nodes , mucosa , and viscera ; cutaneous lesions may be absent. Lesions can regress as immunosuppression is reduced but at the risk of organ rejection. AIDS-associated (epidemic) KS is an AIDS-defining illness ; worldwide, it represents the Most Common HIV-related malignancy . Although the incidence of KS has fallen more than 80% with the advent of aggressive antiretroviral therapies, it still occurs in HIV-infected individuals 300-fold more commonly than in transplant recipients and 1000-fold greater than in the general population. AIDS-associated KS often involves lymph nodes and disseminates widely to viscera early in its course; most patients eventually die of opportunistic infections rather than KS . Cutaneous lesions may occur alone or with visceral lesions of the oral cavity, gastrointestinal tract, and respiratory system. The presence of extensive oral Kaposi sarcoma, as seen in this patient, is associated with a poor prognosis . In classic KS (and sometimes in other variants), the cutaneous lesions progress through three stages : Patches are red-purple macules . Histology shows dilated irregular Endothelial cell-lined vascular spaces with interspersed lymphocytes, plasma cells, and macrophages (sometimes containing hemosiderin ). The lesions can be difficult to distinguish from granulation tissue. With time, lesions become larger, violaceous, raised plaques composed of dermal accumulations of dilated, jagged vascular channels lined and surrounded by plump spindle cells . Scattered between the vascular channels are extravasated erythrocytes, hemosiderin -laden macrophages, and other mononuclear inflammatory cells. Eventually, lesions become nodular and more distinctly neoplastic . These lesions are composed of sheets of plump, proliferating spindle cells, mostly in the dermis or subcutaneous tissues , containing small vessels and slitlike spaces with red cells. Marked hemorrhage, hemosiderin pigment, and mononuclear inflammation are present; mitotic figures are common, as are round, pink, cytoplasmic globules representing degenerating erythrocytes within phagolysosomes. The nodular stage often heralds lymph nodes and visceral involvement . Kaposi sarcoma. (A) Gross photograph illustrating coalescent red-purple macules and plaques of the skin. (B) Histologic appearance of the nodular stage of Kaposi sarcoma, demonstrating sheets of plump, proliferating spindle cells. (B. Courtesy Christopher D. M. Fletcher, MD, Brigham and Women's Hospital, Boston, Mass.)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding malignant vascular tumors except:", "options": [{"label": "A", "text": "They are more cellular and proliferative", "correct": false}, {"label": "B", "text": "They exhibit cellular atypia", "correct": false}, {"label": "C", "text": "They form obvious vascular channels", "correct": true}, {"label": "D", "text": "Usually confirmed by CD 31 or von Willebrand factor", "correct": false}], "correct_answer": "C. They form obvious vascular channels", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>They form obvious vascular channels Malignant vascular tumors are more cellular and more proliferative , and exhibit cytologic atypia ; they usually do NOT form well-organized vessels . The endothelial origin of these tumors can be demonstrated by immunohistochemical staining for CD31 or von Willebrand factor .</p>\n<p><strong>Highyeild:</strong></p><p>Angiosarcoma: Angiosarcomas are malignant endothelial neoplasms with histology varying from highly differentiated tumors that resemble hemangiomas to profoundly anaplastic lesions . Older adults, males, and females , are more commonly affected; angiosarcomas occur at any site, but most often involve skin, soft tissue, breast, and liver. Angiosarcomas can also arise in the setting of lymphedema, classically in the ipsilateral upper extremity several years after radical mastectomy for breast cancer (i.e. after lymph node resection and/or radiation) ; in such cases, the tumor presumably arises from lymphatic vessels (lymphangiosarcoma) . Angiosarcomas have also been induced by radiation and are rarely associated with prolonged insertion of foreign material (e.g., prosthetic devices) . Hepatic angiosarcomas are associated with a variety of carcinogenic exposures including Arsenic (e.g., in pesticides), Thorotrast (a radioactive contrast agent formerly used for radiologic imaging), and polyvinyl chloride (one of the best-known examples of human chemical carcinogenesis). All of these agents have long latencies between initial exposure and eventual tumor development. Angiosarcomas are locally invasive and can readily metastasize , with 5-year survival rates of approximately 30%. Angiosarcoma. (A) Angiosarcoma involving the right ventricle. (B) Moderately differentiated angiosarcoma with dense clumps of atypical cells lining distinct vascular lumens. (C) Immunohistochemical staining for the endothelial cell marker CD31 demonstrating the endothelial nature of the tumor cells.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options: - Option: A. They are more cellular and proliferative. Correct . Option: B. They exhibit cellular atypia. Correct . Option: D. Usually confirmed by CD 31 or von Willebrand factor. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>Malignant vascular tumors are more cellular and more proliferative , and exhibit cytologic atypia ; they usually do NOT form well-organized vessels . The endothelial origin of these tumors can be demonstrated by immunohistochemical staining for CD31 or von Willebrand factor .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 18 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">
Instructions
Test Features:
Multiple choice questions with single correct answers
Timer-based testing for realistic exam conditions
Mark questions for review functionality
Comprehensive results and performance analysis
Mobile-optimized interface for learning on-the-go
Start Test
<!-- Quiz Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="quiz"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <!-- Progress Bar --> <div class="w-full bg-gray-200 rounded-full h-3 mb-4"> <div class="progress-bar h-3 rounded-full" id="progress-bar" style="width: 0%"></div> </div> <!-- Question Header --> <div class="flex flex-col md:flex-row justify-between items-center mb-4"> <h2 class="text-lg font-semibold" id="question-number">Question <span>1</span> of 4</h2> <p class="text-lg font-semibold mt-2 md:mt-0" id="timer">Time Remaining: <span>00:00</span></p> </div> <!-- Question Content --> <div class="mb-6" id="question-content"> <p class="text-gray-800 mb-4" id="question-text"></p> <div class="flex flex-wrap gap-4 mb-4" id="question-images"></div> <div class="space-y-3" id="options"></div> </div> <!-- Navigation Buttons --> <div class="flex flex-col md:flex-row justify-between items-center gap-2 md:gap-4"> <div class="flex gap-2 w-full md:w-auto"> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="previous-btn">Previous</button> <button class="bg-[#2c5281] text-white px-4 py-3 w-full md:w-32 h-14 rounded-lg hover:bg-[#2c5281] transition" id="next-btn">Next</button> </div> <div class="flex items-center gap-2"> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="mark-review"> Review <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> <path d="M10 2a1 1 0 00-1 1v14l3.293-3.293a1 1 0 011.414 0L17 17V3a1 1 0 00-1-1H10z" /> </svg> </button> <button class="bg-transparent text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-100 transition flex items-center gap-1" id="nav-toggle"> Question 🧭 </button> <button class="bg-green-500 text-white px-6 py-3 w-44 h-14 rounded-lg hover:bg-green-600 transition w-full md:w-auto" id="submit-test">Submit Test</button> </div> </div> </section> <!-- Results Section --> <section class="container mx-auto px-4 md:px-6 pt-4 md:pt-6 pb-1 hidden section-transition" id="results"> <div class="bg-white rounded-lg shadow-md p-4 md:p-6"> <h2 class="text-2xl font-semibold mb-4">Anaesthesia Machine - Results</h2> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> <p><strong>Correct:</strong> <span id="correct-count" class="text-[#000000]">0</span></p> <p><strong>Wrong:</strong> <span id="wrong-count" class="text-[#000000]">0</span></p> <p><strong>Unanswered:</strong> <span id="unanswered-count" class="text-[#000000]-500">0</span></p> <p><strong>Marked for Review:</strong> <span id="marked-count" class="text-[#000000]">0</span></p> </div> <h3 class="text-lg font-semibold mb-4" id="result-question-number">Question <span>1</span> of 4</h3> <div class="space-y-6" id="results-content"></div> <div class="result-nav"> <button aria-label="Previous question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" disabled="" id="prev-result">Previous</button> <button aria-label="Toggle results navigation panel" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="results-nav-toggle">Result 🧭</button> <button aria-label="Next question result" class="result-nav-btn bg-[#2c5281] text-white px-6 py-2 rounded-lg hover:bg-[#2c5281] transition" id="next-result">Next</button> </div> <div class="mt-6 flex space-x-4 button-group md:flex-row flex-col"> <button class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition" id="take-again">Take Again</button> </div> </div> </section> <!-- Exit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="exit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Leave Test?</h2> <p class="text-gray-700 mb-4">Your progress will be lost if you leave this page. Are you sure you want to exit?</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="continue-test">No, Continue</button> <button class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition" id="exit-test">Yes, Exit</button> </div> </div> </div> <!-- Submit Confirmation Modal --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 hidden" id="submit-modal" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white rounded-lg p-6 max-w-sm w-full"> <h2 class="text-xl font-semibold mb-4">Confirm Submission</h2> <p class="text-gray-700 mb-2">You have attempted <span id="attempted-count">0</span> of 4 questions.</p> <p class="text-gray-700 mb-4"><span id="unattempted-count">0</span> questions are unattempted.</p> <div class="flex justify-end space-x-4"> <button class="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-400 transition" id="cancel-submit">Cancel</button> <button class="text-white px-4 py-2 rounded-lg hover:bg-[#1a365d] transition" style="background-color: #2c5281;" id="confirm-submit">Submit Test</button> </div> </div> </div> <!-- Quiz Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 nav-panel hidden overflow-y-auto" id="nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Questions Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-nav">Close</button> </div> </div> <!-- Results Navigation Panel --> <div class="fixed inset-0 bg-black bg-opacity-50 flex items-start justify-center p-4 z-50 results-nav-panel hidden overflow-y-auto" id="results-nav-panel" style="align-items: flex-start; padding-top: 33vh;"> <div class="bg-white shadow-lg p-4 rounded-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto"> <h2 class="text-lg font-semibold mb-4">Results Navigation</h2> <div class="mb-4"> <select class="w-full p-2 border rounded-lg text-gray-700" id="results-nav-filter"> <option value="all">All Questions</option> <option value="answered">Answered</option> <option value="unanswered">Unanswered</option> <option value="marked">Marked for Review</option> </select> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> </div> <div class="grid grid-cols-5 gap-2 md:gap-3" id="results-nav-grid"></div> <button class="mt-4 bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition w-full" id="close-results-nav">Close</button> </div> <!-- JavaScript Logic --> <script> // Enable debug mode for detailed logging const DEBUG_MODE = true; // Log debug messages function debugLog(message) { if (DEBUG_MODE) { console.log(`[DEBUG] ${message}`); } } // Initialize questions with error handling let questions = []; let currentResultQuestion = 0; // State for current question in results try { debugLog("Attempting to parse questions_json"); questions = [{"text": "The associated HLA haplotype with Bechet disease is-", "options": [{"label": "A", "text": "B-27", "correct": false}, {"label": "B", "text": "B-51", "correct": true}, {"label": "C", "text": "CW-6", "correct": false}, {"label": "D", "text": "DR-4", "correct": false}], "correct_answer": "B. B-51", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>B-51</p>\n<p><strong>Highyeild:</strong></p><p>Behçet’s disease Behçet’s disease is a clinicopathologic entity characterized by recurrent episodes of oral and genital ulcers, iritis, and cutaneous lesions . The underlying pathologic process is leukocytoclastic venality , although vessels of any size and in any organ can be involved. Essential criteria: Recurrent painful aphthous ulcers involving the oral cavity . The recurrent oral aphthous ulcerations are a sine qua non for the diagnosis . The ulcers persist for 1–2 weeks and subside without leaving scars. Genital ulcers are less common but more specific, are painful, do not affect the glans penis or urethra, and produce scrotal and vulvar scars . There is an association with certain HLA haplotypes ( HLA-B51 , in particular), and a cross-reactive immune response to certain microorganisms is implicated. TH17 cells play a significant role by contributing to the recruitment of neutrophils , which are seen infiltrating vessel walls . Drug of choice: Colchicine . Diagnostic Criteria of Behçet's Syndrome Recurrent oral ulceration plus two of the following: Recurrent genital ulceration Ocular lesions Skin lesions Positive Pathergy test</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. B-27. Associated with Ankylosing Spondylitis. Option: C. CW-6. Associated with Psoriasis. Option: D. DR-4. Associated with Rheumatoid Arthritis.</p>\n<p><strong>Extraedge:</strong></p><p>Important HLA associated with diseases: HLA A3: Hemochromatosis HLA B8: Grave’s disease, Myasthenia gravis HLA B16: Multiple sclerosis HLA B27: Ankylosing Spondylitis, Reactive Arthritis, Reiter’s disease, Psoriatic Spondyloarthropathy HLA B51: Bechet’s disease HLA CW-6: Psoriasis HLA DQ-2/DQ-8: Celiac disease HLA DR-3: Type 1 DM, Dermatitis Herpetiformis, Sjogren’s, SLE HLA DR-5: Pernicious anemia, Hashimoto’s thyroiditis</p>\n<p><strong>Table:</strong></p><p>Vasculitis types based on vessel diameter: Chappel Hill classification: Large: 1. Giant Cell Arteritis 2. Takayasu Arteritis Medium: 1. Polyarteritis Nodosa 2. Kawasaki’s disease Small: 1. Immune complex-mediated: a. Henoch Schonlein Purpura b. Systemic Lupus Erythematosus 2. Pauci immune: a. Churg’s Strauss/ Eosinophilic Granulomatosis\nPolyangiitis b. Wegner’s Granulomatosis/ Granulomatosis\nPolyangiitis c. Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Buerger’s disease except:", "options": [{"label": "A", "text": "It is characterized by a focal acute and chronic vasculitis of small and medium-sized arteries", "correct": false}, {"label": "B", "text": "Luminal thrombosis can be seen", "correct": false}, {"label": "C", "text": "Inflammatory lesion is limited and involve only artery", "correct": true}, {"label": "D", "text": "It has a strong association with cigarette smoking", "correct": false}], "correct_answer": "C. Inflammatory lesion is limited and involve only artery", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Inflammatory lesion is limited and involve only artery</p>\n<p><strong>Highyeild:</strong></p><p>Buerger’s disease/Thromboangitis Obliterans Thromboangiitis obliterans is characterized by segmental, thrombosing, acute and chronic inflammation of medium and small-sized arteries , often leading to vascular insufficiency, typically of the extremities. It occurs almost exclusively in heavy cigarette smokers , usually before the age of 35 . Affected vessels of thromboangiitis obliterans show acute and chronic inflammation , accompanied by luminal thrombosis . The thrombus can contain small microabscesses composed of neutrophils surrounded by granulomatous inflammation , the thrombus may eventually organize and recanalize. Thromboangiitis obliterans (Buerger disease). The lumen is occluded by a thrombus containing abscesses (arrow), and the vessel wall is infiltrated with leukocytes. The inflammatory process extends into contiguous veins and nerves (rare with other forms of vasculitis), and with time all three structures can be encased in fibrous tissue. Early manifestations include the Raynaud phenomenon , instep foot pain induced by exercise (instep claudication) , and superficial nodular phlebitis (venous inflammation) . The vascular insufficiency of Buerger disease tends to be accompanied by severe pain —even at rest—undoubtedly due to neural involvement . Chronic extremity ulcerations can develop, progressing over time (occasionally precipitously) to frank gangrene . Smoking abstinence in the early stages of the disease can often ameliorate further attacks ; however, once established, the vascular lesions do not respond to smoking abstinence .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is characterized by a focal acute and chronic vasculitis of small and medium-sized Correct . Option: B. Luminal thrombosis can be seen. Correct . Option: D. It has a strong association with cigarette smoking. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>It is a diagnosis of exclusion, Olin’s criteria are used. Investigation of choice: Digital Subtraction Angiography . Gold standard investigation: Biopsy showing microabscess with skip areas with preservation of internal elastic lamina .</p>\n<p><strong>Table:</strong></p><p>Vasculitis types based on vessel diameter: Chappel Hill classification: Large: 1. Giant Cell Arteritis 2. Takayasu Arteritis Medium: 1. Polyarteritis Nodosa 2. Kawasaki’s disease Small: 1. Immune complex-mediated: a. Henoch Schonlein Purpura b. Systemic Lupus Erythematosus 2. Pauci immune: a. Churg’s Strauss/ Eosinophilic Granulomatosis Polyangiitis b. Wegner’s Granulomatosis/ Granulomatosis Polyangiitis c. Microscopic polyangiitis</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Churg Strauss syndrome except:", "options": [{"label": "A", "text": "It is a small-vessel vasculitis", "correct": false}, {"label": "B", "text": "It is a type of necrotizing vasculitis", "correct": false}, {"label": "C", "text": "It is also called allergic granulomatosis and angiitis", "correct": false}, {"label": "D", "text": "Inflammatory infiltrate is predominantly neutrophilic", "correct": true}], "correct_answer": "D. Inflammatory infiltrate is predominantly neutrophilic", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Inflammatory infiltrate is predominantly neutrophilic</p>\n<p><strong>Highyeild:</strong></p><p>Churg-Strauss syndrome is a small-vessel necrotizing vasculitis classically associated with asthma, allergic rhinitis, lung infiltrates, peripheral hypereosinophilia, and extravascular necrotizing granuloma . Also called Allergic granulomatosis and angiitis , it is a relatively rare disease. Vascular lesions can be histologically similar to polyarteritis nodosa or microscopic polyangiitis but are also characteristically accompanied by granulomas and eosinophils . Mononeuritis multiplex seen . Cutaneous involvement (with palpable purpura), gastrointestinal bleeding , and renal disease (primarily as focal and segmental glomerulosclerosis) are the major associations. Cytotoxicity produced by the myocardial eosinophilic infiltrates often leads to cardiomyopathy ; cardiac involvement is seen in 60% of patients and is a major cause of morbidity and death . Churg-Strauss syndrome is likely a consequence of hyperresponsiveness to some normally innocuous allergic stimulus. MPO-ANCAs are present in a minority of cases, suggesting that the disorder is pathogenically heterogeneous.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is a small-vessel vasculitis. Correct . Option: B. It is a type of necrotizing vasculitis. Correct . Option: C. It is also called allergic granulomatosis and angiitis. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 35-year-old patient has persistent allergic rhinitis and occasional associated asthmatic episodes with peripheral eosinophilia. Histological findings are shown below. What is your diagnosis?", "options": [{"label": "A", "text": "Microscopic polyangiitis", "correct": false}, {"label": "B", "text": "Churg Strauss syndrome", "correct": true}, {"label": "C", "text": "Kawasaki disease", "correct": false}, {"label": "D", "text": "Wegener's granulomatosis", "correct": false}], "correct_answer": "B. Churg Strauss syndrome", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831083668-QTDP092004IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Churg Strauss syndrome Persistent allergic rhinitis, occasional associated asthmatic episodes with peripheral eosinophilia is suggestive of Churg Strauss syndrome .</p>\n<p><strong>Highyeild:</strong></p><p>Churg-Strauss syndrome is a small-vessel necrotizing vasculitis classically associated with asthma, allergic rhinitis, lung infiltrates, peripheral hypereosinophilia, and extravascular necrotizing granuloma . Also called Allergic granulomatosis and angiitis , it is a relatively rare disease. Vascular lesions can be histologically similar to polyarteritis nodosa or microscopic polyangiitis but are also characteristically accompanied by granulomas and eosinophils . Mononeuritis multiplex seen . Cutaneous involvement (with palpable purpura), gastrointestinal bleeding , and renal disease (primarily as focal and segmental glomerulosclerosis) are the major associations. Cytotoxicity produced by the myocardial eosinophilic infiltrates often leads to cardiomyopathy ; cardiac involvement is seen in 60% of patients and is a major cause of morbidity and death . Churg-Strauss syndrome is likely a consequence of hyperresponsiveness to some normally innocuous allergic stimulus. MPO-ANCAs are present in a minority of cases, suggesting that the disorder is pathogenically heterogeneous.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Microscopic polyangiitis. Incorrect . Option: B. Kawasaki disease. Incorrect . Option: D. Wegener's granulomatosis. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding giant cell arteritis except:", "options": [{"label": "A", "text": "Most commonly seen in old age patients (more than 50 yrs)", "correct": false}, {"label": "B", "text": "Clinical features include vague constitutional symptoms like fever, fatigue, weight loss, and pain along the course temporal artery", "correct": false}, {"label": "C", "text": "50% of patients present with ocular symptoms that range from diplopia to complete vision loss", "correct": false}, {"label": "D", "text": "It usually involves the whole artery", "correct": true}], "correct_answer": "D. It usually involves the whole artery", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It usually involves the whole artery False Giant cell arteritis can be extremely focal within an artery , adequate biopsy requires at least a 1-cm segment ; even then, a negative biopsy result does NOT exclude the diagnosis .</p>\n<p><strong>Highyeild:</strong></p><p>Giant cell (temporal) arteritis Giant cell (temporal) arteritis is a chronic, classically granulomatous inflammation of large- to small-sized arteries that principally affects arteries in the head . The temporal arteries are the disorder since they are the most readily biopsied in making the diagnosis. Vertebral and ophthalmic arteries , as well as the aorta (giant cell aortitis), also can be involved. Giant cell arteritis is rare before the age of 50 . Symptoms may be only vague and constitutional— fever, fatigue, weight loss —or may involve facial pain or headache , most intense along the course of the superficial temporal artery , which can be painful to palpation . Ocular symptoms (associated with involvement of the ophthalmic artery) abruptly appear in about 50% of patients; these range from diplopia to complete vision loss Because ophthalmic artery involvement can lead to sudden and permanent blindness, affected persons must be diagnosed and treated promptly . Involved arterial segments develop intimal thickening (with occasional thromboses) that reduces the luminal diameter. Classic lesions exhibit medial granulomatous inflammation centered on the internal elastic membrane with elastic lamina fragmentation ; there is an infiltration of T cells (CD4+ > CD8+) and macrophages . Although multinucleated giant cells are seen in approximately 75% of adequately biopsied specimens, granulomas and giant cells can be rare or absent. Inflammatory lesions are only focally distributed along the vessel, and segments of relatively normal arteries may be interposed. The healed stage is marked by medial attenuation and scarring with intimal thickening, fragmentation of greater than 30% of the circumference of the internal elastic lamina , and adventitial fibrosis. Giant cell (temporal) arteritis. (A) Hematoxylin-and-eosin stain of section of temporal artery showing giant cells at the degenerated interna elastic membrane in active arteritis (arrow). (B) Elastic tissue stain demonstrating focal destruction of internal elastic membrane (arrow) and intimal thickening (IT) characteristic of long-standing or healed arteritis. (C) The temporal artery of a patient with classic giant cell arteritis shows a thickened, nodular, and tender segment of a vessel on the surface of head (arrow). (C, From Salvarani C, et al. Polymyalgia rheumatica and giant-cell arteritis, N Engl J Med 347:261, 2002.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Most commonly seen in old age patients (more than 50 yrs). True . Option: B. Clinical features include vague constitutional symptoms like fever, fatigue, weight loss, and pain along the course temporal artery. True . Option: C. 50% of patients present with ocular symptoms that range from diplopia to complete vision loss. True .</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis depends on biopsy and histologic confirmation . However, because giant cell arteritis can be extremely focal within an artery , adequate biopsy requires at least a 1-cm segment ; even then, a negative biopsy result does NOT exclude the diagnosis . Corticosteroids or anti-TNF therapies are typically effective.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the pathology of giant cell arteritis except:", "options": [{"label": "A", "text": "Evidence suggests it’s a T cell-mediated immune response against vessel wall antigen", "correct": false}, {"label": "B", "text": "Classical lesions exhibit granulomatous reaction along with giant cell formation", "correct": false}, {"label": "C", "text": "The inflammatory lesion typically involves the whole thickness and length of the artery", "correct": true}, {"label": "D", "text": "Biopsy is the gold standard for diagnosis", "correct": false}], "correct_answer": "C. The inflammatory lesion typically involves the whole thickness and length of the artery", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>The inflammatory lesion typically involves the whole thickness and length of the artery False , Inflammatory lesions are only focally distributed along the vessel, and segments of relatively normal arteries may be interposed.</p>\n<p><strong>Highyeild:</strong></p><p>Giant cell (temporal) arteritis Giant cell (temporal) arteritis is a chronic, classically granulomatous inflammation of large- to small-sized arteries that principally affects arteries in the head . The temporal arteries are the disorder since they are the most readily biopsied in making the diagnosis. Vertebral and ophthalmic arteries , as well as the aorta (giant cell aortitis), also can be involved. Giant cell arteritis is rare before the age of 50 . Symptoms may be only vague and constitutional— fever, fatigue, weight loss —or may involve facial pain or headache , most intense along the course of the superficial temporal artery , which can be painful to palpation . Ocular symptoms (associated with involvement of the ophthalmic artery) abruptly appear in about 50% of patients; these range from diplopia to complete vision loss . Because ophthalmic artery involvement can lead to sudden and permanent blindness, affected persons must be diagnosed and treated promptly . Involved arterial segments develop intimal thickening (with occasional thromboses) that reduces the luminal diameter. Classic lesions exhibit medial granulomatous inflammation centered on the internal elastic membrane with elastic lamina fragmentation ; there is an infiltration of T cells (CD4+ > CD8+) and macrophages . Although multinucleated giant cells are seen in approximately 75% of adequately biopsied specimens, granulomas and giant cells can be rare or absent. Inflammatory lesions are only focally distributed along the vessel, and segments of relatively normal arteries may be interposed. The healed stage is marked by medial attenuation and scarring with intimal thickening, fragmentation of greater than 30% of the circumference of the internal elastic lamina , and adventitial fibrosis. Giant cell (temporal) arteritis. (A) Hematoxylin-and-eosin stain of section of temporal artery showing giant cells at the degenerated internal elastic membrane in active arteritis (arrow). (B) Elastic tissue stain demonstrating focal destruction of internal elastic membrane (arrow) and intimal thickening (IT) characteristic of long-standing or healed arteritis. (C) The temporal artery of a patient with classic giant cell arteritis shows a thickened, nodular, and tender segment of a vessel on the surface of head (arrow). (C, From Salvarani C, et al. Polymyalgia rheumatica and giant-cell arteritis, N Engl J Med 347:261, 2002.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Evidence suggests it's a T cell-mediated immune response against vessel wall antigen. True . Option: B. Classical lesions exhibit granulomatous reaction along with giant cell formation. True . Option: D. Biopsy is the gold standard for diagnosis. True .</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis depends on biopsy and histologic confirmation . However, because giant cell arteritis can be extremely focal within an artery , adequate biopsy requires at least a 1-cm segment ; even then, a negative biopsy result does NOT exclude the diagnosis . Corticosteroids or anti-TNF therapies are typically effective.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "A 57-year-old patient presented with a throbbing headache on one side associated with partial loss of vision and clinical investigation revealed raised ESR. After Conservative therapy, a biopsy was taken from the lesion (as shown in the diagram). What is your diagnosis?", "options": [{"label": "A", "text": "Giant cell arteritis", "correct": true}, {"label": "B", "text": "Takayasu arteritis", "correct": false}, {"label": "C", "text": "Kawasaki disease", "correct": false}, {"label": "D", "text": "Polyarteritis nodosa", "correct": false}], "correct_answer": "A. Giant cell arteritis", "question_images": ["https://dbmi-data.s3.ap-south-1.amazonaws.com/photos-1686831085716-QTDP092007IMG1.JPG"], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Giant cell arteritis History of an elderly patient with a throbbing headache on one side associated with partial loss of vision and raised ESR are highly suggestive of Giant Cell Arteritis.</p>\n<p><strong>Highyeild:</strong></p><p>Giant cell (temporal) arteritis Giant cell (temporal) arteritis is a chronic, classically granulomatous inflammation of large- to small-sized arteries that principally affects arteries in the head . The temporal arteries are the disorder since they are the most readily biopsied in making the diagnosis. Vertebral and ophthalmic arteries , as well as the aorta (giant cell aortitis), also can be involved. Giant cell arteritis is rare before the age of 50 . Symptoms may be only vague and constitutional— fever, fatigue, weight loss —or may involve facial pain or headache , most intense along the course of the superficial temporal artery , which can be painful to palpation . Ocular symptoms (associated with involvement of the ophthalmic artery) abruptly appear in about 50% of patients; these range from diplopia to complete vision loss . Because ophthalmic artery involvement can lead to sudden and permanent blindness, affected persons must be diagnosed and treated promptly . Involved arterial segments develop intimal thickening (with occasional thromboses) that reduces the luminal diameter. Classic lesions exhibit medial granulomatous inflammation centered on the internal elastic membrane with elastic lamina fragmentation ; there is an infiltration of T cells (CD4+ > CD8+) and macrophages . Although multinucleated giant cells are seen in approximately 75% of adequately biopsied specimens, granulomas and giant cells can be rare or absent. Inflammatory lesions are only focally distributed along the vessel, and segments of relatively normal arteries may be interposed. The healed stage is marked by medial attenuation and scarring with intimal thickening, fragmentation of greater than 30% of the circumference of the internal elastic lamina , and adventitial fibrosis. Giant cell (temporal) arteritis. (A) Hematoxylin-and-eosin stain of section of temporal artery showing giant cells at the degenerated interna elastic membrane in active arteritis (arrow). (B) Elastic tissue stain demonstrating focal destruction of internal elastic membrane (arrow) and intimal thickening (IT) characteristic of long-standing or healed arteritis. (C) The temporal artery of a patient with classic giant cell arteritis shows a thickened, nodular, and tender segment of a vessel on the surface of head (arrow). (C, From Salvarani C, et al. Polymyalgia rheumatica and giant-cell arteritis, N Engl J Med 347:261, 2002.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Takayasu arteritis. Incorrect , mostly female patients, age < 40 years present with asymmetric pulses , Raynaud’s phenomenon , etc. Option: C. Kawasaki disease. Incorrect , self-limited l=illness seen in infants and childhood and presents with conjunctival and oral erythema and blistering, edema of the hands and feet, erythema of the palms and soles, a desquamative rash, and cervical lymph node enlargement . Option: D. Polyarteritis nodosa. Incorrect , is primarily a disease of young adults but can occur in all age groups. It is frequently remitting and episodic , with long symptom-free intervals. The typical presentation involves some combination of rapidly accelerating hypertension due to renal artery involvement; abdominal pain and bloody stools , diffuse myalgias, and peripheral neuritis , predominantly affecting motor nerves .</p>\n<p><strong>Extraedge:</strong></p><p>Diagnosis depends on biopsy and histologic confirmation . However, because giant cell arteritis can be extremely focal within an artery , adequate biopsy requires at least a 1-cm segment ; even then, a negative biopsy result does NOT exclude the diagnosis . Corticosteroids or anti-TNF therapies are typically effective.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Wegener’s granulomatosis except:", "options": [{"label": "A", "text": "It is a T cell-mediated hypersensitivity response", "correct": false}, {"label": "B", "text": "Associated with raised PR3 ANCA levels", "correct": false}, {"label": "C", "text": "Limited Wegener's granulomatosis involves only the lung", "correct": false}, {"label": "D", "text": "It can show granuloma in renal involvement", "correct": true}], "correct_answer": "D. It can show granuloma in renal involvement", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It can show granuloma in renal involvement False , granulomas are not seen in kidneys, instead, glomerulonephritis is seen .</p>\n<p><strong>Highyeild:</strong></p><p>Granulomatosis With Polyangiitis (GPA) Previously called Wegener granulomatosis is a necrotizing vasculitis characterized by a triad of: Acute necrotizing granulomas of the upper respiratory tract (ear, nose, sinuses, throat) or the lower respiratory tract (lung) or both . Necrotizing or granulomatous vasculitis affecting small- to medium-sized vessels (e.g. capillaries, venules, arterioles, and arteries), most prominent in the lungs and upper airways but affecting other sites as well . Focal necrotizing, often crescentic, glomerulonephritis . “Limited” forms of GPA may be restricted to the respiratory tract. Conversely, a widespread form of the disease can affect eyes, skin, and other organs, notably the heart; clinically, widespread GPA resembles PAN except that there is also respiratory involvement. Pathogenesis: GPA likely represents a form of T cell-mediated hypersensitivity response to normally “innocuous” inhaled microbial or other environmental agents. PR3-ANCAs are also present in up to 95% of cases. Following immunosuppression treatment, PR3-ANCA titers fall dramatically; subsequent rising titers are predictive of relapse . Renal lesions range from mild, focal glomerular necrosis with isolated capillary loop thrombosis (focal and segmental necrotizing glomerulonephritis) to more advanced glomerular lesions with diffuse necrosis with parietal cell proliferation resulting in crescent formation ( crescentic glomerulonephritis). Males are affected more often than females, at an average age of about 40 years . Classic features include bilateral pneumonitis with nodules and cavitary lesions (95%), chronic sinusitis (90%), mucosal ulcerations of the nasopharynx (75%), and renal disease (80%). Rashes, myalgias, articular involvement, neuritis, and fever can also occur. Left untreated, the disease is usually rapidly fatal with 80% mortality within 1 year. Treatment with steroids , cyclophosphamide , TNF antagonists , and anti–B-cell antibodies , have turned GPA into a chronic relapsing and remitting disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is a T cell-mediated hypersensitivity response. Correct . Option: B. Associated with raised PR3 ANCA levels. Correct . Option: C. Limited Wegener's granulomatosis involves only the lung. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following histological findings can be seen in renal involvement by Wegner’s granulomatosis except:", "options": [{"label": "A", "text": "Focal and segmental glomerulonephritis", "correct": false}, {"label": "B", "text": "Minimal parietal cell proliferation", "correct": false}, {"label": "C", "text": "Interstitial granuloma", "correct": true}, {"label": "D", "text": "Crescentic granuloma", "correct": false}], "correct_answer": "C. Interstitial granuloma", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Interstitial granuloma In early stages, glomeruli exhibit only focal necrosis with isolated capillary loop thrombosis ( focal and segmental necrotizing glomerulonephritis ); there is minimal parietal cell proliferation in the Bowman capsule. More advanced glomerular lesions are characterized by diffuse necrosis with exuberant parietal cell proliferation resulting in crescent formation ( crescentic glomerulonephritis ).</p>\n<p><strong>Highyeild:</strong></p><p>Granulomatosis With Polyangiitis (GPA) Previously called Wegener granulomatosis is a necrotizing vasculitis characterized by a triad of: Acute necrotizing granulomas of the upper respiratory tract (ear, nose, sinuses, throat) or the lower respiratory tract (lung) or both . Necrotizing or granulomatous vasculitis affecting small- to medium-sized vessels (e.g. capillaries, venules, arterioles, and arteries), most prominent in the lungs and upper airways but affecting other sites as well . Focal necrotizing, often crescentic, glomerulonephritis . “Limited” forms of GPA may be restricted to the respiratory tract. Conversely, a widespread form of the disease can affect eyes, skin, and other organs, notably the heart; clinically, widespread GPA resembles PAN except that there is also respiratory involvement. Pathogenesis: GPA likely represents a form of T cell-mediated hypersensitivity response to normally “innocuous” inhaled microbial or other environmental agents. PR3-ANCAs are also present in up to 95% of cases. Following immunosuppression treatment, PR3-ANCA titers fall dramatically; subsequent rising titers are predictive of relapse . Renal lesions range from mild, focal glomerular necrosis with isolated capillary loop thrombosis (focal and segmental necrotizing glomerulonephritis) to more advanced glomerular lesions with diffuse necrosis with parietal cell proliferation resulting in crescent formation ( crescentic glomerulonephritis). Males are affected more often than females, at an average age of about 40 years . Classic features include bilateral pneumonitis with nodules and cavitary lesions (95%), chronic sinusitis (90%), mucosal ulcerations of the nasopharynx (75%), and renal disease (80%). Rashes, myalgias, articular involvement, neuritis, and fever can also occur. Left untreated, the disease is usually rapidly fatal with 80% mortality within 1 year. Treatment with steroids , cyclophosphamide , TNF antagonists , and anti–B-cell antibodies , have turned GPA into a chronic relapsing and remitting disease.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Focal and segmental glomerulonephritis. Correct . Option: B. Minimal parietal cell proliferation. Correct . Option: D. Crescentic granuloma. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Kawasaki disease except:", "options": [{"label": "A", "text": "It is also known as mucocutaneous syndrome", "correct": false}, {"label": "B", "text": "It is an acute febrile, usually self-limited illness of infancy and childhood", "correct": false}, {"label": "C", "text": "It has a predilection for renal and pulmonary vasculature", "correct": true}, {"label": "D", "text": "Vascular damage is primarily mediated by T cells and macrophages", "correct": false}], "correct_answer": "C. It has a predilection for renal and pulmonary vasculature", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It has a predilection for renal and pulmonary vasculature False , primarily it has a predilection for coronary arteries .</p>\n<p><strong>Highyeild:</strong></p><p>Kawasaki disease typically presents with conjunctival and oral erythema and blistering, edema of the hands and feet, erythema of the palms and soles, a desquamative rash, and cervical lymph node enlargement (hence its other name, mucocutaneous lymph node syndrome ). It is an acute febrile, usually self-limited illness of infancy and childhood (80% of patients are 4 years old or younger); it is associated with arteritis affecting large to medium-sized , and even small vessels . Its clinical significance stems primarily from a predilection for coronary artery involvement that can cause aneurysms that rupture or thrombose, resulting in acute myocardial infarctions . The pathogenesis of Kawasaki disease is unknown. A variety of infectious agents (mostly viral) have been implicated in triggering the disease in genetically susceptible individuals. The vascular damage is primarily mediated by activated T cells and monocytes/macrophages . Treatment: I/V Ig and Aspirin Never give steroids</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is also known as mucocutaneous syndrome. Correct . Option: B. It is an acute febrile, usually self-limited illness of infancy and childhood. Correct . Option: D. Vascular damage is primarily mediated by T cells and macrophages. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>MNEMONIC for Kawasaki disease: “Apply CREAM when riding Kawasaki bike” > 5 days of fever C: Conjunctivitis (nonpurulent) R: Rash (polymorphic) E: Edema of palms and soles A: LymphAdenopathy M: Mucosal inflammation of tongue (strawberry red tongue)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "The statement is true regarding histological findings of Kawasaki disease except for:", "options": [{"label": "A", "text": "There is dense transmural inflammatory infiltrate", "correct": false}, {"label": "B", "text": "Acute vasculitis subsides spontaneously or in response to treatment", "correct": false}, {"label": "C", "text": "Pathological changes are significant in cardiovascular and extra cardiovascular organ", "correct": true}, {"label": "D", "text": "Inflammation causes vessel wall damage and can lead to aneurysm formation", "correct": false}], "correct_answer": "C. Pathological changes are significant in cardiovascular and extra cardiovascular organ", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Pathological changes are significant in cardiovascular and extra cardiovascular organ False , pathologic changes outside the cardiovascular system are rarely significant. The vasculitis resembles that seen in Polyarteritis Nodosa (PAN). There is a dense transmural inflammatory infiltrate , although the fibrinoid necrosis is usually less prominent than in PAN. A cute vasculitis typically subsides spontaneously or in response to treatment , but aneurysm formation due to wall damage can supervene. As with other arteritides, healed lesions can also exhibit obstructive intimal thickening. Pathologic changes outside the cardiovascular system are rarely significant .</p>\n<p><strong>Highyeild:</strong></p><p>Kawasaki disease typically presents with conjunctival and oral erythema and blistering, edema of the hands and feet, erythema of the palms and soles, a desquamative rash, and cervical lymph node enlargement (hence its other name, mucocutaneous lymph node syndrome ). It is an acute febrile, usually self-limited illness of infancy and childhood (80% of patients are 4 years old or younger); it is associated with arteritis affecting large to medium-sized , and even small vessels . Its clinical significance stems primarily from a predilection for coronary artery involvement that can cause aneurysms that rupture or thrombose, resulting in acute myocardial infarctions . The pathogenesis of Kawasaki disease is unknown. A variety of infectious agents (mostly viral) have been implicated in triggering the disease in genetically susceptible individuals. The vascular damage is primarily mediated by activated T cells and monocytes/macrophages . Treatment: I/V Ig and Aspirin Never give steroids</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. There is dense transmural inflammatory infiltrate. Correct . Option: B. Acute vasculitis subsides spontaneously or in response to treatment. Correct . Option: D. Inflammation causes vessel wall damage and can lead to aneurysm formation. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>MNEMONIC for Kawasaki disease: “Apply CREAM when riding Kawasaki bike” > 5 days of fever C: Conjunctivitis (nonpurulent) R: Rash (polymorphic) E: Edema of palms and soles A: LymphAdenopathy M: Mucosal inflammation of tongue (strawberry red tongue)</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding microscopic polyangiitis except:", "options": [{"label": "A", "text": "It is also called hypersensitivity vasculitis or leukocytoclastic vasculitis", "correct": false}, {"label": "B", "text": "It can involve the skin, lungs, brain, heart, kidney, and muscles", "correct": false}, {"label": "C", "text": "It is a necrotizing vasculitis that generally affects capillaries, as well as small arterioles and venules", "correct": false}, {"label": "D", "text": "Recruitment and activation of T cells and macrophages are responsible for inflammatory lesions", "correct": true}], "correct_answer": "D. Recruitment and activation of T cells and macrophages are responsible for inflammatory lesions", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Recruitment and activation of T cells and macrophages are responsible for inflammatory lesions False , recruitment and activation of neutrophils within affected vascular beds are likely responsible for the disease manifestations</p>\n<p><strong>Highyeild:</strong></p><p>Microscopic polyangiitis is a necrotizing vasculitis that generally affects capillaries, as well as small arterioles and venules . Unlike PAN, all lesions of microscopic polyangiitis tend to be of the same age in any given patient , suggesting a single episode of antibody or immune complex deposition. It is also called hypersensitivity vasculitis or leukocytoclastic vasculitis . The skin, mucous membranes, lungs, brain, heart, gastrointestinal tract, kidneys, and muscles can all be involved . Microscopic polyangiitis is characterized by segmental fibrinoid necrosis of the media with focal transmural necrotizing lesions ; granulomatous inflammation is ABSENT . These lesions morphologically resemble PAN but typically spare medium-sized and larger arteries; consequently, macroscopic infarcts are uncommon. Recruitment and activation of neutrophils within affected vascular beds are likely responsible for the disease manifestations. Depending on the vascular bed involved, major clinical features include hemoptysis , hematuria and proteinuria , bowel pain or bleeding , muscle pain or weakness , and palpable cutaneous purpura .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is also called hypersensitivity vasculitis or leukocytoclastic vasculitis. Correct . Option: B. It can involve skin, lungs, brain, heart, kidney, and muscle. Correct . Option: C. It is a necrotizing vasculitis that generally affects capillaries, as well as small arterioles and venules. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>With the exception of those who develop widespread renal or brain involvement, immunosuppression induces remission and markedly improves long-term survival.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following are true regarding histological features of microscopic polyangiitis except:", "options": [{"label": "A", "text": "It is characterized by segmental fibrinoid necrosis of the media", "correct": false}, {"label": "B", "text": "It can show focal transmural necrotizing lesions", "correct": false}, {"label": "C", "text": "Granulomatous inflammation is seen", "correct": true}, {"label": "D", "text": "Neutrophilic infiltration and its apoptosis can be seen in post-capillary venules", "correct": false}], "correct_answer": "C. Granulomatous inflammation is seen", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Granulomatous inflammation is seen False , Granulomatous inflammation is ABSENT .</p>\n<p><strong>Highyeild:</strong></p><p>Microscopic Polyangiitis Microscopic Polyangiitis is a necrotizing vasculitis that generally affects capillaries, as well as small arterioles and venules . Unlike PAN, all lesions of microscopic polyangiitis tend to be of the same age in any given patient , suggesting a single episode of antibody or immune complex deposition. It is also called hypersensitivity vasculitis or leukocytoclastic vasculitis . The skin, mucous membranes, lungs, brain, heart, gastrointestinal tract, kidneys, and muscles can all be involved . Microscopic polyangiitis is characterized by segmental fibrinoid necrosis of the media with focal transmural necrotizing lesions ; granulomatous inflammation is ABSENT . These lesions morphologically resemble PAN but typically spare medium-sized and larger arteries; consequently, macroscopic infarcts are uncommon. Recruitment and activation of neutrophils within affected vascular beds are likely responsible for the disease manifestations Depending on the vascular bed involved, major clinical features include hemoptysis , hematuria and proteinuria , bowel pain or bleeding , muscle pain or weakness , and palpable cutaneous purpura . With the exception of those who develop widespread renal or brain involvement, immunosuppression induces remission and markedly improves long-term survival.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is characterized by segmental fibrinoid necrosis of the media. Correct . Option: B. It can show focal transmural necrotizing lesions. Correct . Option: D. Neutrophilic infiltration and its apoptosis can be seen in postcapillary Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding polyarteritis nodosa except:", "options": [{"label": "A", "text": "It is a systemic vasculitis of small- or medium-sized muscular arteries", "correct": false}, {"label": "B", "text": "30% of cases are associated with HBsAg-HBsAb complexes", "correct": false}, {"label": "C", "text": "It is also associated with ANCA", "correct": true}, {"label": "D", "text": "Typically affects renal and visceral vessels but spares the pulmonary circulation", "correct": false}], "correct_answer": "C. It is also associated with ANCA", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It is also associated with ANCA False , there is NO association with ANCA</p>\n<p><strong>Highyeild:</strong></p><p>Polyarteritis nodosa (PAN) PAN is a systemic vasculitis of small- or medium-sized muscular arteries that typically affects renal and visceral vessels but SPARES the pulmonary circulation . There is NO association with ANCA , but about 30% of patients with PAN have chronic hepatitis B and deposits containing HBsAg-HBsAb complexes in affected vessels. The cause remains unknown in the majority of cases. Clinical manifestations result from ischemia and infarction of affected tissues and organs. PAN is associated with segmental transmural necrotizing inflammation of small- to medium-sized arteries , often with superimposed aneurysms and/or thrombosis . Kidney, heart, liver, and gastrointestinal tract vessels are involved in descending order of frequency. Lesions usually involve only part of the vessel circumference with a predilection for branch points . During the acute phase, there is transmural inflammation of the arterial wall with a mixed infiltrate of neutrophils, eosinophils, and mononuclear cells , frequently accompanied by fibrinoid necrosis and luminal thrombosis. Older lesions show fibrous thickening of the vessel wall extending into the adventitia . Characteristically, all stages of activity (from early to late) coexist in different vessels or even within the same vessel , suggesting ongoing injury. Polyarteritis nodosa. There is segmental fibrinoid necrosis and thrombotic occlusion of the lumen of this small artery. Note that part of the vessel wall at the upper right (arrow) is uninvolved. (Courtesy Sidney Murphree, MD, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is a systemic vasculitis of small- or medium-sized muscular arteries. Correct . Option: B. 30% of cases are associated with HBsAg-HBsAb complexes. Correct . Option: D. Typically affects renal and visceral vessels but spares the pulmonary circulation. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>PAN is primarily a disease of young adults but can occur in all age groups. The course is frequently remitting and episodic , with long symptom-free intervals. The typical presentation involves some combination of rapidly accelerating hypertension due to renal artery involvement; abdominal pain and bloody stools , diffuse myalgias; and peripheral neuritis , predominantly affecting motor nerves. Renal involvement is often a major cause of mortality. Untreated, PAN is typically fatal; however, immunosuppression can yield remissions or cure in 90% of cases.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "False statement regarding histological features of PAN is:", "options": [{"label": "A", "text": "Segmental transmural necrotizing inflammation of small- to medium-sized arteries", "correct": false}, {"label": "B", "text": "In the acute phase fibrinoid necrosis can be seen", "correct": false}, {"label": "C", "text": "Late stage show fibrosis, thrombosis", "correct": false}, {"label": "D", "text": "All vessels will be in the same stage of inflammation", "correct": true}], "correct_answer": "D. All vessels will be in the same stage of inflammation", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>All vessels will be in the same stage of inflammation False , characteristically, all stages of activity (from early to late) coexist in different vessels or even within the same vessel , suggesting ongoing injury.</p>\n<p><strong>Highyeild:</strong></p><p>Polyarteritis nodosa (PAN) PAN is a systemic vasculitis of small- or medium-sized muscular arteries that typically affects renal and visceral vessels but SPARES the pulmonary circulation . There is NO association with ANCA , but about 30% of patients with PAN have chronic hepatitis B and deposits containing HBsAg-HBsAb complexes in affected vessels. The cause remains unknown in the majority of cases. Clinical manifestations result from ischemia and infarction of affected tissues and organs. PAN is associated with segmental transmural necrotizing inflammation of small- to medium-sized arteries , often with superimposed aneurysms and/or thrombosis . Kidney, heart, liver, and gastrointestinal tract vessels are involved in descending order of frequency. Lesions usually involve only part of the vessel circumference with a predilection for branch points . During the acute phase, there is transmural inflammation of the arterial wall with a mixed infiltrate of neutrophils, eosinophils, and mononuclear cells , frequently accompanied by fibrinoid necrosis and luminal thrombosis. Older lesions show fibrous thickening of the vessel wall extending into the adventitia . Characteristically, all stages of activity (from early to late) coexist in different vessels or even within the same vessel , suggesting ongoing injury. Polyarteritis nodosa. There is segmental fibrinoid necrosis and thrombotic occlusion of the lumen of this small artery. Note that part of the vessel wall at the upper right (arrow) is uninvolved. (Courtesy Sidney Murphree, MD, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Segmental transmural necrotizing inflammation of small- to medium-sized arteries. Correct . Option: B. In the acute phase, fibrinoid necrosis can be seen. Correct . Option: C. Late stage show fibrosis, and thrombosis. Correct .</p>\n<p><strong>Extraedge:</strong></p><p>PAN is primarily a disease of young adults but can occur in all age groups. The course is frequently remitting and episodic , with long symptom-free intervals. The typical presentation involves some combination of rapidly accelerating hypertension due to renal artery involvement; abdominal pain and bloody stools , diffuse myalgias; and peripheral neuritis , predominantly affecting motor nerves. Renal involvement is often a major cause of mortality. Untreated, PAN is typically fatal; however, immunosuppression can yield remissions or cure in 90% of cases.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Polyarteritis nodosa can involve any visceral vessel but spares the vasculature of-", "options": [{"label": "A", "text": "Heart", "correct": false}, {"label": "B", "text": "Kidney", "correct": false}, {"label": "C", "text": "Lung", "correct": true}, {"label": "D", "text": "Stomach", "correct": false}], "correct_answer": "C. Lung", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lung Polyarteritis nodosa (PAN) is a systemic vasculitis of small- or medium-sized muscular arteries, typically involving renal and visceral vessels but sparing the pulmonary circulation .</p>\n<p><strong>Highyeild:</strong></p><p>Polyarteritis nodosa (PAN) PAN is a systemic vasculitis of small- or medium-sized muscular arteries that typically affects renal and visceral vessels but SPARES the pulmonary circulation . There is NO association with ANCA , but about 30% of patients with PAN have chronic hepatitis B and deposits containing HBsAg-HBsAb complexes in affected vessels. The cause remains unknown in the majority of cases. Clinical manifestations result from ischemia and infarction of affected tissues and organs. PAN is associated with segmental transmural necrotizing inflammation of small- to medium-sized arteries , often with superimposed aneurysms and/or thrombosis . Kidney, heart, liver, and gastrointestinal tract vessels are involved in descending order of frequency. Lesions usually involve only part of the vessel circumference with a predilection for branch points . During the acute phase, there is transmural inflammation of the arterial wall with a mixed infiltrate of neutrophils, eosinophils, and mononuclear cells , frequently accompanied by fibrinoid necrosis and luminal thrombosis. Older lesions show fibrous thickening of the vessel wall extending into the adventitia . Characteristically, all stages of activity (from early to late) coexist in different vessels or even within the same vessel , suggesting ongoing injury. Polyarteritis nodosa. There is segmental fibrinoid necrosis and thrombotic occlusion of the lumen of this small artery. Note that part of the vessel wall at the upper right (arrow) is uninvolved. (Courtesy Sidney Murphree, MD, Department of Pathology, University of Texas Southwestern Medical School, Dallas, Tex.)</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Heart. Incorrect . Option: B. Kidney. Incorrect . Option: D. Stomach. Incorrect .</p>\n<p><strong>Extraedge:</strong></p><p>PAN is primarily a disease of young adults but can occur in all age groups. The course is frequently remitting and episodic , with long symptom-free intervals. The typical presentation involves some combination of rapidly accelerating hypertension due to renal artery involvement; abdominal pain and bloody stools , diffuse myalgias; and peripheral neuritis , predominantly affecting motor nerves. Renal involvement is often a major cause of mortality. Untreated, PAN is typically fatal; however, immunosuppression can yield remissions or cure in 90% of cases.</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding Takayasu arteritis except:", "options": [{"label": "A", "text": "It is also called pulseless disease", "correct": false}, {"label": "B", "text": "It affects patients older than 50 years of age", "correct": true}, {"label": "C", "text": "It causes transmural thickening of blood vessels leading to narrowing of the lumen", "correct": false}, {"label": "D", "text": "With disease progression it leads to reduced blood pressure and pulses in upper extremities", "correct": false}], "correct_answer": "B. It affects patients older than 50 years of age", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>It affects patients older than 50 years of age False , usually seen in patients younger than 50 years of age .</p>\n<p><strong>Highyeild:</strong></p><p>Takayasu Arteritis Takayasu arteritis is a granulomatous vasculitis of medium and larger arteries characterized principally by ocular disturbances and marked weakening of the pulses in the upper extremities (hence the name pulseless disease ). Takayasu arteritis manifests with transmural fibrous thickening of the aorta —particularly the aortic arch and great vessels—with severe luminal narrowing of the major branch vessels . Takayasu aortitis shares many attributes with giant cell aortitis, including clinical features and histology; indeed, the distinction is typically made based on the age of the patient . Those over 50 years of age are designated as giant cell aortitis , while those under 50 are designated as Takayasu aortitis . Takayasu arteritis classically involves the aortic arch . In a third of patients, it also affects the remainder of the aorta and its branches, with pulmonary artery involvement in half of the cases ; coronary and renal arteries may be similarly affected. There is an irregular thickening of the vessel wall with intimal hyperplasia ; when the aortic arch is involved, the great vessel lumens can be markedly narrowed or even obliterated. Such narrowing explains the weakness of the peripheral pulses . Histologically the changes range from adventitial mononuclear infiltrates with perivascular cuffing of the vasa vasorum to intense mononuclear inflammation in the media . Granulomatous inflammation, replete with giant cells and patchy medial necrosis, is also seen The histology is essentially indistinguishable from the giant cell (temporal) arteritis . As the disease progresses, collagenous scarring, with admixed chronic inflammatory infiltrates, occurs in all three layers of the vessel wall. Occasionally, aortic root involvement causes dilation and aortic valve insufficiency. Takayasu arteritis. (A) Aortic arch angiogram showing narrowing of brachiocephalic, carotid, and subclavian arteries (arrows). (B) Gross photograph of two cross-sections of the right carotid artery taken at autopsy of the patient shown in (A) demonstrating marked intimal thickening and adventitial fibrosis with minimal residual lumen. (C) Histologic appearance in active Takayasu aortitis illustrating destruction and fibrosis of the arterial media associated with mononuclear infiltrates and inflammatory giant cells (arrows). Initial symptoms are usually nonspecific, including fatigue, weight loss, and fever . With progression, vascular symptoms appear and dominate the clinical picture, including reduced blood pressure and weaker pulses in the upper extremities ; ocular disturbances, including visual defects, retinal hemorrhages, and total blindness ; and neurologic deficits . Involvement of the renal arteries leads to systemic hypertension in roughly half of patients. In some patients, there is rapid progression, while others enter a quiescent stage at 1 to 2 years, permitting long-term survival, albeit with visual or neurologic deficits.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It is also called pulseless disease. Correct . Option: C. It causes transmural thickening of blood vessels leading to the narrowing of the lumen. Correct . Option: D. With disease progression, it leads to reduced blood pressure and pulses in the upper extremities. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding the pathology of Takayasu arteritis except:", "options": [{"label": "A", "text": "It classically involves aortic arch", "correct": false}, {"label": "B", "text": "There is a dense mononuclear inflammatory infiltrate, granulomatous reaction along with giant cell formation", "correct": false}, {"label": "C", "text": "With the progression of the disease collagenous scarring with admixed chronic inflammatory infiltrate occurs in all three layers of vessel wall", "correct": false}, {"label": "D", "text": "Coronary and renal vessels are not involved", "correct": true}], "correct_answer": "D. Coronary and renal vessels are not involved", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Coronary and renal vessels are not involved False , narrowing of the coronary ostia may lead to myocardial infarction , and involvement of the renal arteries leads to systemic hypertension in roughly half of patients.</p>\n<p><strong>Highyeild:</strong></p><p>Takayasu Arteritis Takayasu arteritis is a granulomatous vasculitis of medium and larger arteries characterized principally by ocular disturbances and marked weakening of the pulses in the upper extremities (hence the name pulseless disease ). Takayasu arteritis manifests with transmural fibrous thickening of the aorta —particularly the aortic arch and great vessels—with severe luminal narrowing of the major branch vessels . Takayasu aortitis shares many attributes with giant cell aortitis, including clinical features and histology; indeed, the distinction is typically made based on the age of the patient . Those over 50 years of age are designated as giant cell aortitis , while those under 50 are designated as Takayasu aortitis . Takayasu arteritis classically involves the aortic arch . In a third of patients, it also affects the remainder of the aorta and its branches, with pulmonary artery involvement in half of the cases ; coronary and renal arteries may be similarly affected. There is an irregular thickening of the vessel wall with intimal hyperplasia ; when the aortic arch is involved, the great vessel lumens can be markedly narrowed or even obliterated. Such narrowing explains the weakness of the peripheral pulses . Histologically the changes range from adventitial mononuclear infiltrates with perivascular cuffing of the vasa vasorum to intense mononuclear inflammation in the media . Granulomatous inflammation, replete with giant cells and patchy medial necrosis, is also seen. The histology is essentially indistinguishable from the giant cell (temporal) arteritis . As the disease progresses, collagenous scarring, with admixed chronic inflammatory infiltrates, occurs in all three layers of the vessel wall. Occasionally, aortic root involvement causes dilation and aortic valve insufficiency. Takayasu arteritis. (A) Aortic arch angiogram showing narrowing of brachiocephalic, carotid, and subclavian arteries (arrows). (B) Gross photograph of two cross-sections of the right carotid artery taken at autopsy of the patient shown in (A) demonstrating marked intimal thickening and adventitial fibrosis with minimal residual lumen. (C) Histologic appearance in active Takayasu aortitis illustrating destruction and fibrosis of the arterial media associated with mononuclear infiltrates and inflammatory giant cells (arrows). Initial symptoms are usually nonspecific, including fatigue, weight loss, and fever . With progression, vascular symptoms appear and dominate the clinical picture, including reduced blood pressure and weaker pulses in the upper extremities ; ocular disturbances, including visual defects, retinal hemorrhages, and total blindness ; and neurologic deficits . Involvement of the renal arteries leads to systemic hypertension in roughly half of patients. In some patients, there is rapid progression, while others enter a quiescent stage at 1 to 2 years, permitting long-term survival, albeit with visual or neurologic deficits.</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. It classically involves an aortic arch. Correct . Option: B. There is a dense mononuclear inflammatory infiltrate, granulomatous reaction along with giant cell formation. Correct . Option: C. With the progression of the disease collagenous scarring with admixed chronic inflammatory infiltrate occurs in all three layers of the vessel Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All the following statements are true regarding antineutrophil cytoplasmic antibodies except:", "options": [{"label": "A", "text": "C-ANCA antigen is proteinase 3", "correct": false}, {"label": "B", "text": "P-ANCA antigen is MPO", "correct": false}, {"label": "C", "text": "C-ANCA induced by several therapeutic agents, particularly propylthiouracil", "correct": true}, {"label": "D", "text": "ANCAs are very useful diagnostic markers, their titers generally mirror the clinical severity", "correct": false}], "correct_answer": "C. C-ANCA induced by several therapeutic agents, particularly propylthiouracil", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>C-ANCA induced by several therapeutic agents, particularly propylthiouracil False , MPO-ANCAs are induced by several therapeutic agents , particularly propylthiouracil . ANCAs are very useful diagnostic markers ; their titers generally mirror the clinical severity , and a rise in titers after periods of quiescence is predictive of disease recurrence . Anti-proteinase-3 ( PR3-ANCA , previously c-ANCA ). PR3 is a neutrophil azurophilic granule constituent . Anti-myeloperoxidase ( MPO-ANCA , previously p-ANCA ). MPO is a lysosomal granule constituent involved in oxygen-free radical generation. MPO-ANCAs are induced by several therapeutic agents , particularly propylthiouracil . MPO-ANCAs are associated with microscopic polyangiitis and Churg-Strauss syndrome .</p>\n<p><strong>Highyeild:</strong></p><p>Small vessel vasculitis: Small vessel vasculitis ANCA RPGN Granuloma on microscopy Clinical features Churg Strauss/ Eosinophilic Granulomatosis Polyangiitis P ANCA Seen Seen ● Allergic rhinitis ● Asthma ● Eosinophilia ● Mononeuritis multiplex Wegner’s Granulomatosis/ Granulomatosis with Polyangiitis C ANCA Seen Seen ● Upper respiratory tract illness: Otitis media, sinusitis, Saddle nose, Septal perforation, gum inflammation/ strawberry gum). ● Lower respiratory tract illness: Lung cavitation, ILD, Peripheral cavities Microscopic Polyangiitis P ANCA Seen Absent ● Diffuse Alveolar Hemorrhage ● Hemoptysis</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. C-ANCA antigen is proteinase 3. Correct . Option: B. P-ANCA antigen is MPO. Correct . Option: D. ANCAs are very useful diagnostic markers, their titers generally mirror the clinical severity. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "All of the following statements are true regarding lymphangitis except:", "options": [{"label": "A", "text": "Klebsiella and E. coli are the most common organism causing lymphangitis", "correct": true}, {"label": "B", "text": "Affected lymphatic vessels dilated and filled with exudate of neutrophil and monocytes", "correct": false}, {"label": "C", "text": "Clinically manifestations are red, painful subcutaneous streaks and painful enlargement of the draining lymph nodes", "correct": false}, {"label": "D", "text": "If the organism escapes into the venous circulation it can cause bacteremia and sepsis", "correct": false}], "correct_answer": "A. Klebsiella and E. coli are the most common organism causing lymphangitis", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Klebsiella and E. coli are the most common organism causing lymphangitis False , Group A β-hemolytic streptococci are the most common agent , although any microbe can be causal.</p>\n<p><strong>Highyeild:</strong></p><p>Lymphangitis represents acute inflammation elicited by the spread of bacterial infections into lymphatics; group A β-hemolytic streptococci are the most common agent , although any microbe can be causal. Affected lymphatics are dilated and filled with an exudate of neutrophils and monocytes ; the infiltrates can extend through the vessel wall, and in severe cases, can produce cellulitis or focal abscesses . Lymphangitis is manifested by red, painful subcutaneous streaks (the inflamed lymphatics), and painful enlargement of the draining lymph nodes (lymphadenitis) . If bacteria are not successfully contained within the lymph nodes, subsequent escape into the venous circulatio n can result in bacteremia or sepsis . Primary lymphedema can occur as an isolated congenital defect ( simple congenital lymphedema ) or as the familial Milroy disease ( heredofamilial congenital lymphedema ), which results in lymphatic agenesis or hypoplasia . Secondary or obstructive lymphedema stems from blockage of previously normal lymphatics, including Tumors obstructing lymphatic channels or the regional lymph nodes. Surgical procedures that sever lymphatic connections (e.g., axillary lymph node resection in a radical mastectomy). Postradiation fibrosis . Filariasis . Postinflammatory thrombosis and scarring . Regardless of the cause, lymphedema increases the hydrostatic pressure in the lymphatics distal to the obstruction and causes edema . Chronic edema, in turn, can lead to ECM deposition and fibrosis, producing brawny induration or a peau d’orange (orange peel) appearance on the overlying skin. Eventually, inadequate tissue perfusion can lead to skin ulceration . Rupture of dilated lymphatics (e.g., secondary to obstruction from a tumor or following surgical injury) leads to milky accumulations of lymph designated as chylous ascites (abdomen), chylothorax, and hydropericardium .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: B. Affected lymphatic vessels dilated and filled with exudate of neutrophils and monocytes. Correct . Option: C. Clinically manifestations are red, painful subcutaneous streaks and painful enlargement of the draining lymph nodes. Correct . Option: D. If the organism escapes into the venous circulation it can cause bacteremia and sepsis. Correct .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}, {"text": "Milroy disease is related to:", "options": [{"label": "A", "text": "Phleobothrombosis", "correct": false}, {"label": "B", "text": "Vasculitis", "correct": false}, {"label": "C", "text": "Lymphangitis", "correct": false}, {"label": "D", "text": "Lymphedema", "correct": true}], "correct_answer": "D. Lymphedema", "question_images": [], "explanation_images": [], "explanation": "<p><strong>Solution:</strong></p><p>Lymphedema Lymphangitis represents acute inflammation elicited by the spread of bacterial infections into lymphatics; group A β-hemolytic streptococci are the most common agent , although any microbe can be causal. Affected lymphatics are dilated and filled with an exudate of neutrophils and monocytes ; the infiltrates can extend through the vessel wall, and in severe cases, can produce cellulitis or focal abscesses . Lymphangitis is manifested by red, painful subcutaneous streaks (the inflamed lymphatics), and painful enlargement of the draining lymph nodes (lymphadenitis) . If bacteria are not successfully contained within the lymph nodes, subsequent escape into the venous circulatio n can result in bacteremia or sepsis . Primary lymphedema can occur as an isolated congenital defect ( simple congenital lymphedema ) or as the familial Milroy disease ( heredofamilial congenital lymphedema ), which results in lymphatic agenesis or hypoplasia . Secondary or obstructive lymphedema stems from blockage of previously normal lymphatics, including Tumors obstructing lymphatic channels or the regional lymph nodes. Surgical procedures that sever lymphatic connections (e.g., axillary lymph node resection in a radical mastectomy). Postradiation fibrosis . Filariasis . Postinflammatory thrombosis and scarring . Regardless of the cause, lymphedema increases the hydrostatic pressure in the lymphatics distal to the obstruction and causes edema . Chronic edema, in turn, can lead to ECM deposition and fibrosis, producing brawny induration or a peau d’orange (orange peel) appearance on the overlying skin. Eventually, inadequate tissue perfusion can lead to skin ulceration . Rupture of dilated lymphatics (e.g., secondary to obstruction from a tumor or following surgical injury) leads to milky accumulations of lymph designated as chylous ascites (abdomen), chylothorax, and hydropericardium .</p>\n<p><strong>Highyeild:</strong></p><p>Lymphangitis represents acute inflammation elicited by the spread of bacterial infections into lymphatics; group A β-hemolytic streptococci are the most common agent , although any microbe can be causal. Affected lymphatics are dilated and filled with an exudate of neutrophils and monocytes ; the infiltrates can extend through the vessel wall, and in severe cases, can produce cellulitis or focal abscesses . Lymphangitis is manifested by red, painful subcutaneous streaks (the inflamed lymphatics), and painful enlargement of the draining lymph nodes (lymphadenitis) . If bacteria are not successfully contained within the lymph nodes, subsequent escape into the venous circulatio n can result in bacteremia or sepsis . Primary lymphedema can occur as an isolated congenital defect ( simple congenital lymphedema ) or as the familial Milroy disease ( heredofamilial congenital lymphedema ), which results in lymphatic agenesis or hypoplasia . Secondary or obstructive lymphedema stems from blockage of previously normal lymphatics, including Tumors obstructing lymphatic channels or the regional lymph nodes. Surgical procedures that sever lymphatic connections (e.g., axillary lymph node resection in a radical mastectomy). Postradiation fibrosis . Filariasis . Postinflammatory thrombosis and scarring . Regardless of the cause, lymphedema increases the hydrostatic pressure in the lymphatics distal to the obstruction and causes edema . Chronic edema, in turn, can lead to ECM deposition and fibrosis, producing brawny induration or a peau d’orange (orange peel) appearance on the overlying skin. Eventually, inadequate tissue perfusion can lead to skin ulceration . Rupture of dilated lymphatics (e.g., secondary to obstruction from a tumor or following surgical injury) leads to milky accumulations of lymph designated as chylous ascites (abdomen), chylothorax, and hydropericardium .</p>\n<p><strong>Random:</strong></p><p>Explanation for incorrect options:- Option: A. Phleobothrombosis. Incorrect . Option: B. Vasculitis. Incorrect . Option: C. Lymphangitis. Incorrect .</p>\n<p>@dams_new_robot</p>", "bot": "@dams_new_robot", "video": ""}]; if (!Array.isArray(questions) || questions.length === 0) { throw new Error("Questions data is empty or invalid"); } debugLog(`Successfully parsed ${questions.length} questions`); } catch (e) { console.error("Failed to parse questions_json:", e); document.getElementById('error-message').innerHTML = "Error loading quiz data. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; // Fallback to sample questions for testing questions = [ { text: "What is 2 + 2?", options: [ { label: "A", text: "3", correct: false }, { label: "B", text: "4", correct: true }, { label: "C", text: "5", correct: false }, { label: "D", text: "6", correct: false } ], correct_answer: "B. 4", question_images: [], explanation_images: [], explanation: "<p>2 + 2 = 4</p><p>@dams_new_robot</p>", bot: "@dams_new_robot", audio: "", video: "" } ]; debugLog("Loaded fallback questions"); } // Quiz state let currentQuestion = 0; let answers = new Array(questions.length).fill(null); let markedForReview = new Array(questions.length).fill(false); let timeRemaining = 31 * 60; // Duration in seconds let timerInterval = null; const quizId = `{title.replace(/\s+/g, '_').toLowerCase()}`; // Unique ID for local storage // Load saved progress function loadProgress() { try { debugLog("Loading progress from localStorage"); const saved = localStorage.getItem(`quiz_${quizId}`); if (saved) { const { savedAnswers, savedMarked, savedTime } = JSON.parse(saved); answers = savedAnswers || answers; markedForReview = savedMarked || markedForReview; timeRemaining = savedTime !== undefined ? savedTime : timeRemaining; debugLog("Progress loaded successfully"); } else { debugLog("No saved progress found"); } } catch (e) { console.error("Error loading progress:", e); debugLog("Failed to load progress: " + e.message); } } // Save progress function saveProgress() { try { debugLog("Saving progress to localStorage"); localStorage.setItem(`quiz_${quizId}`, JSON.stringify({ savedAnswers: answers, savedMarked: markedForReview, savedTime: timeRemaining })); debugLog("Progress saved successfully"); } catch (e) { console.error("Error saving progress:", e); debugLog("Failed to save progress: " + e.message); } } // Initialize quiz function initQuiz() { try { debugLog("Initializing quiz"); loadProgress(); const startButton = document.getElementById('start-test'); if (!startButton) { throw new Error("Start test button not found"); } startButton.addEventListener('click', startQuiz); debugLog("Start test button listener attached"); document.getElementById('previous-btn').addEventListener('click', showPreviousQuestion); document.getElementById('next-btn').addEventListener('click', showNextQuestion); document.getElementById('mark-review').addEventListener('click', toggleMarkForReview); document.getElementById('nav-toggle').addEventListener('click', toggleNavPanel); document.getElementById('submit-test').addEventListener('click', showSubmitModal); document.getElementById('continue-test').addEventListener('click', closeExitModal); document.getElementById('exit-test').addEventListener('click', () => { debugLog("Exiting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('cancel-submit').addEventListener('click', closeSubmitModal); document.getElementById('confirm-submit').addEventListener('click', submitTest); document.getElementById('take-again').addEventListener('click', () => { debugLog("Restarting test"); localStorage.removeItem(`quiz_${quizId}`); window.location.reload(); }); document.getElementById('close-nav').addEventListener('click', toggleNavPanel); document.getElementById('nav-filter').addEventListener('change', updateNavPanel); document.getElementById('prev-result').addEventListener('click', showPreviousResult); document.getElementById('next-result').addEventListener('click', showNextResult); document.getElementById('results-nav-toggle').addEventListener('click', toggleResultsNavPanel); document.getElementById('close-results-nav').addEventListener('click', toggleResultsNavPanel); document.getElementById('results-nav-filter').addEventListener('change', updateResultsNavPanel); debugLog("Quiz initialized successfully"); } catch (e) { console.error("Failed to initialize quiz:", e); debugLog("Failed to initialize quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('start-test').disabled = true; } } // Start quiz function startQuiz() { try { debugLog("Starting quiz"); document.getElementById('instructions').classList.add('hidden'); document.getElementById('quiz').classList.remove('hidden'); showQuestion(currentQuestion); startTimer(); updateNavPanel(); debugLog("Quiz started successfully"); } catch (e) { console.error("Error starting quiz:", e); debugLog("Failed to start quiz: " + e.message); document.getElementById('error-message').innerHTML = "Error starting quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); document.getElementById('quiz').classList.add('hidden'); document.getElementById('instructions').classList.remove('hidden'); } } // Show question function showQuestion(index) { try { debugLog(`Showing question ${index + 1}`); currentQuestion = index; const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } document.getElementById('question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('question-text').innerHTML = q.text || "No question text available"; const imagesDiv = document.getElementById('question-images'); imagesDiv.innerHTML = q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg">`).join('') : ''; const optionsDiv = document.getElementById('options'); optionsDiv.innerHTML = q.options && q.options.length > 0 ? q.options.map(opt => ` <button class="option-btn w-full text-left p-3 border rounded-lg ${answers[index] === opt.label ? 'selected' : ''}" onclick="selectOption(${index}, '${opt.label}')" aria-label="Option ${opt.label}: ${opt.text}"> ${opt.label}. ${opt.text} </button> `).join('') : '<p class="text-red-500">No options available</p>'; document.getElementById('previous-btn').disabled = index === 0; document.getElementById('next-btn').disabled = index === questions.length - 1; document.getElementById('mark-review').classList.toggle('marked', markedForReview[index]); updateProgressBar(); saveProgress(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying question:", e); debugLog("Failed to display question: " + e.message); } } // Select option function selectOption(index, label) { try { debugLog(`Selecting option ${label} for question ${index + 1}`); answers[index] = label; const optionsDiv = document.getElementById('options'); const optionButtons = optionsDiv.querySelectorAll('.option-btn'); optionButtons.forEach(btn => { const btnLabel = btn.textContent.trim().split('.')[0]; btn.classList.toggle('selected', btnLabel === label); }); updateNavPanel(); saveProgress(); debugLog(`Option ${label} selected for question ${index + 1}`); } catch (e) { console.error("Error selecting option:", e); debugLog("Failed to select option: " + e.message); } } // Toggle mark for review function toggleMarkForReview() { try { debugLog(`Toggling mark for review on question ${currentQuestion + 1}`); markedForReview[currentQuestion] = !markedForReview[currentQuestion]; document.getElementById('mark-review').classList.toggle('marked', markedForReview[currentQuestion]); updateNavPanel(); saveProgress(); debugLog(`Mark for review toggled for question ${currentQuestion + 1}`); } catch (e) { console.error("Error marking for review:", e); debugLog("Failed to mark for review: " + e.message); } } // Navigate to previous question function showPreviousQuestion() { try { debugLog(`Navigating to previous question from ${currentQuestion + 1}`); if (currentQuestion > 0) { currentQuestion--; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to previous question:", e); debugLog("Failed to navigate to previous question: " + e.message); } } // Navigate to next question function showNextQuestion() { try { debugLog(`Navigating to next question from ${currentQuestion + 1}`); if (currentQuestion < questions.length - 1) { currentQuestion++; showQuestion(currentQuestion); } } catch (e) { console.error("Error navigating to next question:", e); debugLog("Failed to navigate to next question: " + e.message); } } // Handle question navigation click function handleQuestionNavClick(index) { try { debugLog(`Navigating to question ${index + 1} via nav panel`); showQuestion(index); toggleNavPanel(); } catch (e) { console.error("Error handling navigation click:", e); debugLog("Failed to navigate via nav panel: " + e.message); } } // Start timer function startTimer() { try { debugLog("Starting timer"); timerInterval = setInterval(() => { if (timeRemaining <= 0) { debugLog("Timer expired, submitting test"); clearInterval(timerInterval); submitTest(); } else { timeRemaining--; const minutes = Math.floor(timeRemaining / 60); const seconds = timeRemaining % 60; document.getElementById('timer').innerHTML = `Time Remaining: <span>${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}</span>`; saveProgress(); } }, 1000); debugLog("Timer started successfully"); } catch (e) { console.error("Error starting timer:", e); debugLog("Failed to start timer: " + e.message); } } // Update progress bar function updateProgressBar() { try { debugLog("Updating progress bar"); const progress = ((currentQuestion + 1) / questions.length) * 100; document.getElementById('progress-bar').style.width = `${progress}%`; debugLog("Progress bar updated"); } catch (e) { console.error("Error updating progress bar:", e); debugLog("Failed to update progress bar: " + e.message); } } // Update quiz navigation panel function updateNavPanel() { try { debugLog("Updating quiz navigation panel"); const filter = document.getElementById('nav-filter').value; const navGrid = document.getElementById('nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="question-nav-btn ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleQuestionNavClick(${i})" aria-label="Go to Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Quiz navigation panel updated"); } catch (e) { console.error("Error updating quiz navigation panel:", e); debugLog("Failed to update quiz navigation panel: " + e.message); } } // Update results navigation panel function updateResultsNavPanel() { try { debugLog("Updating results navigation panel"); const filter = document.getElementById('results-nav-filter').value; const navGrid = document.getElementById('results-nav-grid'); navGrid.innerHTML = questions.map((_, i) => { if (filter === 'answered' && !answers[i]) return ''; if (filter === 'unanswered' && answers[i]) return ''; if (filter === 'marked' && !markedForReview[i]) return ''; return ` <button class="result-nav-btn-grid ${answers[i] ? 'answered' : 'unanswered'} ${markedForReview[i] ? 'marked-nav' : ''}" onclick="handleResultNavClick(${i})" aria-label="Go to Result for Question ${i + 1}"> ${i + 1} </button> `; }).join(''); debugLog("Results navigation panel updated"); } catch (e) { console.error("Error updating results navigation panel:", e); debugLog("Failed to update results navigation panel: " + e.message); } } // Toggle quiz navigation panel function toggleNavPanel() { try { debugLog("Toggling quiz navigation panel"); const navPanel = document.getElementById('nav-panel'); navPanel.classList.toggle('hidden'); debugLog("Quiz navigation panel toggled"); } catch (e) { console.error("Error toggling quiz navigation panel:", e); debugLog("Failed to toggle quiz navigation panel: " + e.message); } } // Toggle results navigation panel function toggleResultsNavPanel() { try { debugLog("Toggling results navigation panel"); const resultsNavPanel = document.getElementById('results-nav-panel'); resultsNavPanel.classList.toggle('hidden'); if (!resultsNavPanel.classList.contains('hidden')) { updateResultsNavPanel(); } debugLog("Results navigation panel toggled"); } catch (e) { console.error("Error toggling results navigation panel:", e); debugLog("Failed to toggle results navigation panel: " + e.message); } } // Handle result navigation click function handleResultNavClick(index) { try { debugLog(`Navigating to result for question ${index + 1} via nav panel`); showResults(index); toggleResultsNavPanel(); } catch (e) { console.error("Error handling result navigation click:", e); debugLog("Failed to navigate to result: " + e.message); } } // Show submit modal function showSubmitModal() { try { debugLog("Showing submit modal"); const attempted = answers.filter(a => a !== null).length; document.getElementById('attempted-count').textContent = attempted; document.getElementById('unattempted-count').textContent = questions.length - attempted; document.getElementById('submit-modal').classList.remove('hidden'); debugLog("Submit modal displayed"); } catch (e) { console.error("Error showing submit modal:", e); debugLog("Failed to show submit modal: " + e.message); } } // Close submit modal function closeSubmitModal() { try { debugLog("Closing submit modal"); document.getElementById('submit-modal').classList.add('hidden'); debugLog("Submit modal closed"); } catch (e) { console.error("Error closing submit modal:", e); debugLog("Failed to close submit modal: " + e.message); } } // Close exit modal function closeExitModal() { try { debugLog("Closing exit modal"); document.getElementById('exit-modal').classList.add('hidden'); debugLog("Exit modal closed"); } catch (e) { console.error("Error closing exit modal:", e); debugLog("Failed to close exit modal: " + e.message); } } // Submit test function submitTest() { try { debugLog("Submitting test"); clearInterval(timerInterval); document.getElementById('quiz').classList.add('hidden'); document.getElementById('submit-modal').classList.add('hidden'); document.getElementById('results').classList.remove('hidden'); showResults(0); // Start with first question // Trigger confetti animation confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); localStorage.removeItem(`quiz_${quizId}`); debugLog("Test submitted successfully"); } catch (e) { console.error("Error submitting test:", e); debugLog("Failed to submit test: " + e.message); } } function showResults(index) { try { debugLog(`Showing result for question ${index + 1}`); currentResultQuestion = index; let correct = 0, wrong = 0, unanswered = 0, marked = 0; answers.forEach((answer, i) => { const isCorrect = answer && questions[i].options.find(opt => opt.label === answer)?.correct; if (answer === null) unanswered++; else if (isCorrect) correct++; else wrong++; if (markedForReview[i]) marked++; }); const q = questions[index]; if (!q) { throw new Error(`Question ${index} is undefined`); } const userAnswer = answers[index]; const isCorrect = userAnswer && q.options.find(opt => opt.label === userAnswer)?.correct; const resultsContent = document.getElementById('results-content'); // Create scrollable container for explanation content resultsContent.innerHTML = ` <div class="border-4 ${isCorrect ? 'border-green-600 bg-green-100' : userAnswer ? 'border-red-600 bg-red-100' : 'border-gray-400 bg-gray-50'} p-4 rounded-lg overflow-hidden"> <p class="font-semibold">Question ${index + 1}: ${q.text || 'No question text'}</p> ${q.question_images && q.question_images.length > 0 ? q.question_images.map(url => `<img src="${url}" alt="Question Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} <p><strong>Your Answer:</strong> ${userAnswer ? `${userAnswer}. ${q.options.find(opt => opt.label === userAnswer)?.text || 'Invalid option'}` : 'Unanswered'}</p> <p><strong>Correct Answer:</strong> ${q.correct_answer || 'Unknown'}</p> <!-- Scrollable container for explanation --> <div class="mt-2 overflow-x-auto"> ${q.explanation || 'No explanation available'} </div> ${q.explanation_images && q.explanation_images.length > 0 ? q.explanation_images.map(url => `<img src="${url}" alt="Explanation Image" class="max-w-full h-auto rounded-lg my-2">`).join('') : ''} ${q.video ? ` <button class="play-video bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadVideo(this, '${q.video}', 'video-${index}')" aria-label="Play explanation video for Question ${index + 1}"> Play Video Explanation </button> <div id="video-${index}" class="video-container mt-2"></div> ` : '<p class="text-gray-500 mt-2">No video available</p>'} ${q.audio ? ` <button class="play-audio bg-[#2c5281] text-white px-4 py-2 rounded-lg mt-2" onclick="loadAudio(this, '${q.audio}', 'audio-${index}')" aria-label="Play audio explanation for Question ${index + 1}"> Play Audio Explanation </button> <div id="audio-${index}" class="audio-container mt-2"></div> ` : ''} </div> `; document.getElementById('correct-count').textContent = correct; document.getElementById('wrong-count').textContent = wrong; document.getElementById('unanswered-count').textContent = unanswered; document.getElementById('marked-count').textContent = marked; document.getElementById('result-question-number').innerHTML = `Question <span>${index + 1}</span> of ${questions.length}`; document.getElementById('prev-result').disabled = index === 0; document.getElementById('next-result').disabled = index === questions.length - 1; updateResultsNavPanel(); window.scrollTo({ top: 0, behavior: 'smooth' }); debugLog(`Result for question ${index + 1} displayed successfully`); } catch (e) { console.error("Error displaying result:", e); debugLog("Failed to display result: " + e.message); } } // Navigate to previous result function showPreviousResult() { try { debugLog(`Navigating to previous result from question ${currentResultQuestion + 1}`); if (currentResultQuestion > 0) { showResults(currentResultQuestion - 1); } } catch (e) { console.error("Error navigating to previous result:", e); debugLog("Failed to navigate to previous result: " + e.message); } } // Navigate to next result function showNextResult() { try { debugLog(`Navigating to next result from question ${currentResultQuestion + 1}`); if (currentResultQuestion < questions.length - 1) { showResults(currentResultQuestion + 1); } } catch (e) { console.error("Error navigating to next result:", e); debugLog("Failed to navigate to next result: " + e.message); } } // Lazy-load video function loadVideo(button, videoUrl, containerId) { try { debugLog(`Loading video for ${containerId}: ${videoUrl}`); if (!videoUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No video available</p>`; button.remove(); debugLog("No video URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <div class="video-loading"></div> <video controls class="w-full max-w-[600px] rounded-lg" preload="metadata" aria-label="Video explanation"> <source src="${videoUrl}" type="${videoUrl.endsWith('.m3u8') ? 'application/x-mpegURL' : 'video/mp4'}"> Your browser does not support the video tag. </video> `; container.classList.add('active'); button.remove(); // Initialize HLS.js for .m3u8 videos const video = container.querySelector('video'); if (videoUrl.endsWith('.m3u8') && Hls.isSupported()) { const hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(Hls.Events.ERROR, (event, data) => { console.error("HLS.js error:", data); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("HLS.js error: " + JSON.stringify(data)); }); } else if (videoUrl.endsWith('.m3u8') && video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // Handle video load errors video.onerror = () => { console.error("Video load error for URL:", videoUrl); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; debugLog("Video load error for URL: " + videoUrl); }; // Remove loading spinner when video is ready video.onloadedmetadata = () => { container.querySelector('.video-loading').remove(); debugLog("Video loaded successfully"); }; } catch (e) { console.error("Error loading video:", e); debugLog("Failed to load video: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading video. <a href="${videoUrl}" target="_blank" aria-label="Open video in new tab">Open video</a></p>`; } } // Lazy-load audio function loadAudio(button, audioUrl, containerId) { try { debugLog(`Loading audio for ${containerId}: ${audioUrl}`); if (!audioUrl) { const container = document.getElementById(containerId); container.innerHTML = `<p class="text-gray-500">No audio available</p>`; button.remove(); debugLog("No audio URL provided"); return; } const container = document.getElementById(containerId); container.innerHTML = ` <audio controls class="w-full max-w-[600px]" preload="metadata" aria-label="Audio explanation"> <source src="${audioUrl}" type="audio/mpeg"> Your browser does not support the audio tag. </audio> `; container.classList.add('active'); button.remove(); // Handle audio load errors const audio = container.querySelector('audio'); audio.onerror = () => { console.error("Audio load error for URL:", audioUrl); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; debugLog("Audio load error for URL: " + audioUrl); }; debugLog("Audio loaded successfully"); } catch (e) { console.error("Error loading audio:", e); debugLog("Failed to load audio: " + e.message); const container = document.getElementById(containerId); container.innerHTML = `<p class="text-red-500">Error loading audio. <a href="${audioUrl}" target="_blank" aria-label="Open audio in new tab">Open audio</a></p>`; } } // Toggle dark mode function toggleTheme() { try { debugLog("Toggling theme"); document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); debugLog("Theme toggled successfully"); } catch (e) { console.error("Error toggling theme:", e); debugLog("Failed to toggle theme: " + e.message); } } // Load theme preference function loadTheme() { try { debugLog("Loading theme preference"); const theme = localStorage.getItem('theme'); if (theme === 'dark') { document.documentElement.classList.add('dark'); } debugLog("Theme loaded successfully"); } catch (e) { console.error("Error loading theme:", e); debugLog("Failed to load theme: " + e.message); } } // Initialize on DOM content loaded window.addEventListener('DOMContentLoaded', () => { try { debugLog("DOM content loaded, initializing quiz"); loadTheme(); initQuiz(); } catch (e) { console.error("Error during DOMContentLoaded:", e); debugLog("Failed to initialize on DOMContentLoaded: " + e.message); document.getElementById('error-message').innerHTML = "Error initializing quiz. Please check the console for details or contact support."; document.getElementById('error-message').classList.remove('hidden'); } }); </script> </body> </html>" frameborder="0" width="100%" height="2000px">